"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _a, _FooterService_checkFooterExist, _FooterService_checkFooterItemExist;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FooterService = void 0;
const uuid_1 = require("uuid");
const database_1 = require("../application/database");
const response_error_1 = require("../error/response-error");
const footer_model_1 = require("../model/footer-model");
const footer_validation_1 = require("../validation/footer-validation");
const validation_1 = require("../validation/validation");
class FooterService {
    static create(request) {
        return __awaiter(this, void 0, void 0, function* () {
            // Validate the create request
            const createRequest = validation_1.Validation.validate(footer_validation_1.FooterValidation.CREATE, request);
            // Generate a UUID for the new footer
            const footerId = (0, uuid_1.v4)();
            // Insert the new footer into the database with the UUID
            yield database_1.db.query('INSERT INTO footer (id, name, type, `order`) VALUES (?, ?, ?, ?)', [
                footerId,
                createRequest.name,
                createRequest.type,
                createRequest.order,
            ]);
            // Retrieve the newly created footer by the UUID
            const footer = yield database_1.db.queryOne('SELECT * FROM footer WHERE id = ? LIMIT 1', [
                footerId,
            ]);
            if (!footer) {
                throw new response_error_1.ResponseError(500, 'Failed to create footer');
            }
            // Initialize the items array for the footer
            footer.items = [];
            return (0, footer_model_1.toFooterResponse)(footer);
        });
    }
    static getAll() {
        return __awaiter(this, void 0, void 0, function* () {
            // Query to get all footers ordered by 'order' field
            const footers = yield database_1.db.query('SELECT * FROM footer ORDER BY `order` ASC');
            // Query to get all footer items
            const footerItems = yield database_1.db.query('SELECT * FROM footer_item ORDER BY created_at ASC');
            // Map footer items to their respective footers
            const footersWithItems = footers.map((footer) => {
                const items = footerItems.filter((item) => item.footer_id === footer.id);
                return Object.assign(Object.assign({}, footer), { items });
            });
            // Map each footer to the response format
            return footersWithItems.map(footer_model_1.toFooterResponse);
        });
    }
    static get(id) {
        return __awaiter(this, void 0, void 0, function* () {
            // Retrieve single footer by ID
            const footer = yield database_1.db.queryOne('SELECT * FROM footer WHERE id = ? LIMIT 1', [
                id,
            ]);
            if (!footer) {
                throw new response_error_1.ResponseError(404, 'Footer not found');
            }
            // Retrieve the items associated with the footer
            const footerItems = yield database_1.db.query('SELECT * FROM footer_item WHERE footer_id = ? ORDER BY created_at ASC', [id]);
            // Add the items to the footer object
            footer.items = footerItems;
            return (0, footer_model_1.toFooterResponse)(footer);
        });
    }
    static update(id, request) {
        return __awaiter(this, void 0, void 0, function* () {
            // Check if the footer exists
            const existingFooter = yield database_1.db.queryOne('SELECT id FROM footer WHERE id = ? LIMIT 1', [id]);
            if (!existingFooter) {
                throw new response_error_1.ResponseError(404, 'Footer not found');
            }
            // Validate the update request
            const updateRequest = validation_1.Validation.validate(footer_validation_1.FooterValidation.UPDATE, request);
            // Update the footer in the database
            yield database_1.db.query('UPDATE footer SET name = ? WHERE id = ?', [updateRequest.name, id]);
            // Retrieve the updated footer by the ID
            const footer = yield database_1.db.queryOne('SELECT * FROM footer WHERE id = ? LIMIT 1', [
                id,
            ]);
            if (!footer) {
                throw new response_error_1.ResponseError(500, 'Failed to update footer');
            }
            // Retrieve the items associated with the updated footer
            const footerItems = yield database_1.db.query('SELECT * FROM footer_item WHERE footer_id = ?', [id]);
            // Add the items to the footer object
            footer.items = footerItems;
            return (0, footer_model_1.toFooterResponse)(footer);
        });
    }
    static updateVisibility(id, visible) {
        return __awaiter(this, void 0, void 0, function* () {
            // Check if the footer exists
            yield __classPrivateFieldGet(this, _a, "m", _FooterService_checkFooterExist).call(this, id);
            // Update the visibility of the footer in the database
            yield database_1.db.query('UPDATE footer SET visible = ? WHERE id = ?', [visible, id]);
            // Retrieve the updated footer by ID
            const footer = yield database_1.db.queryOne('SELECT * FROM footer WHERE id = ? LIMIT 1', [
                id,
            ]);
            if (!footer) {
                throw new response_error_1.ResponseError(500, 'Failed to update footer visibility');
            }
            // Retrieve the items associated with the updated footer
            const footerItems = yield database_1.db.query('SELECT * FROM footer_item WHERE footer_id = ?', [id]);
            // Add the items to the footer object
            footer.items = footerItems;
            return (0, footer_model_1.toFooterResponse)(footer);
        });
    }
    static updateOrder(request) {
        return __awaiter(this, void 0, void 0, function* () {
            // Validate the update order request
            const updateRequests = validation_1.Validation.validate(footer_validation_1.FooterValidation.UPDATE_ORDER, request);
            // Start a transaction for batch processing
            yield database_1.db.transaction((conn) => __awaiter(this, void 0, void 0, function* () {
                for (const updateRequest of updateRequests) {
                    // Check if the footer exists
                    const [existingFooter] = yield conn.query('SELECT id FROM footer WHERE id = ? LIMIT 1', [updateRequest.id]);
                    if (!existingFooter) {
                        throw new response_error_1.ResponseError(404, 'Footer not found');
                    }
                    // Update the footer in the database
                    yield conn.query('UPDATE footer SET `order` = ? WHERE id = ?', [updateRequest.order, updateRequest.id]);
                }
            }));
        });
    }
    static delete(id) {
        return __awaiter(this, void 0, void 0, function* () {
            // Check if the footer exists
            const existingFooter = yield database_1.db.queryOne('SELECT id FROM footer WHERE id = ? LIMIT 1', [id]);
            if (!existingFooter) {
                throw new response_error_1.ResponseError(404, 'Footer not found');
            }
            // Delete the footer from the database
            yield database_1.db.query('DELETE FROM footer WHERE id = ?', [id]);
        });
    }
    static createItem(footerId, request) {
        return __awaiter(this, void 0, void 0, function* () {
            // Check if the footer exists
            yield __classPrivateFieldGet(this, _a, "m", _FooterService_checkFooterExist).call(this, footerId);
            // Validate the create request
            const createRequest = validation_1.Validation.validate(footer_validation_1.FooterValidation.CREATE_ITEM, request);
            // Generate a UUID for the new footer item
            const itemId = (0, uuid_1.v4)();
            // Insert the new footer item into the database with the UUID
            yield database_1.db.query('INSERT INTO footer_item (id, footer_id, name, url) VALUES (?, ?, ?, ?)', [
                itemId,
                footerId,
                createRequest.name,
                createRequest.url,
            ]);
            // Retrieve the newly created footer item by the UUID
            const footerItem = yield database_1.db.queryOne('SELECT * FROM footer_item WHERE id = ? LIMIT 1', [itemId]);
            if (!footerItem) {
                throw new response_error_1.ResponseError(500, 'Failed to create footer item');
            }
            return (0, footer_model_1.toFooterItemResponse)(footerItem);
        });
    }
    static updateItem(footerId, itemId, request) {
        return __awaiter(this, void 0, void 0, function* () {
            // Check if the footer exists
            yield __classPrivateFieldGet(this, _a, "m", _FooterService_checkFooterExist).call(this, footerId);
            // Check if the footer item exists
            yield __classPrivateFieldGet(this, _a, "m", _FooterService_checkFooterItemExist).call(this, footerId, itemId);
            // Validate the update request
            const updateRequest = validation_1.Validation.validate(footer_validation_1.FooterValidation.UPDATE_ITEM, request);
            // Update the footer item in the database
            yield database_1.db.query('UPDATE footer_item SET name = ?, url = ? WHERE id = ?', [
                updateRequest.name,
                updateRequest.url,
                itemId,
            ]);
            // Retrieve the updated footer item by the ID
            const footerItem = yield database_1.db.queryOne('SELECT * FROM footer_item WHERE id = ? LIMIT 1', [itemId]);
            if (!footerItem) {
                throw new response_error_1.ResponseError(500, 'Failed to update footer item');
            }
            return (0, footer_model_1.toFooterItemResponse)(footerItem);
        });
    }
    static updateItemVisibility(footerId, itemId, visible) {
        return __awaiter(this, void 0, void 0, function* () {
            // Check if the footer exists
            yield __classPrivateFieldGet(this, _a, "m", _FooterService_checkFooterExist).call(this, footerId);
            // Check if the footer item exists
            yield __classPrivateFieldGet(this, _a, "m", _FooterService_checkFooterItemExist).call(this, footerId, itemId);
            // Update the visibility of the footer item in the database
            yield database_1.db.query('UPDATE footer_item SET visible = ? WHERE id = ?', [visible, itemId]);
            // Retrieve the updated footer item by the ID
            const footerItem = yield database_1.db.queryOne('SELECT * FROM footer_item WHERE id = ? LIMIT 1', [itemId]);
            if (!footerItem) {
                throw new response_error_1.ResponseError(500, 'Failed to update footer item visibility');
            }
            return (0, footer_model_1.toFooterItemResponse)(footerItem);
        });
    }
    static deleteItem(footerId, itemId) {
        return __awaiter(this, void 0, void 0, function* () {
            // Check if the footer exists
            yield __classPrivateFieldGet(this, _a, "m", _FooterService_checkFooterExist).call(this, footerId);
            // Check if the footer item exists
            yield __classPrivateFieldGet(this, _a, "m", _FooterService_checkFooterItemExist).call(this, footerId, itemId);
            // Delete the footer item from the database
            yield database_1.db.query('DELETE FROM footer_item WHERE id = ?', [itemId]);
        });
    }
}
exports.FooterService = FooterService;
_a = FooterService, _FooterService_checkFooterExist = function _FooterService_checkFooterExist(id) {
    return __awaiter(this, void 0, void 0, function* () {
        // Check if the footer exists
        const existingFooter = yield database_1.db.queryOne('SELECT id FROM footer WHERE id = ? LIMIT 1', [id]);
        if (!existingFooter) {
            throw new response_error_1.ResponseError(404, 'Footer not found');
        }
    });
}, _FooterService_checkFooterItemExist = function _FooterService_checkFooterItemExist(footerId, itemId) {
    return __awaiter(this, void 0, void 0, function* () {
        // Check if the footer item exists
        const existingFooterItem = yield database_1.db.queryOne('SELECT id FROM footer_item WHERE id = ? AND footer_id = ? LIMIT 1', [itemId, footerId]);
        if (!existingFooterItem) {
            throw new response_error_1.ResponseError(404, 'Footer item not found');
        }
    });
};
