"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());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProductOrderService = void 0;
const uuid_1 = require("uuid");
const database_1 = require("../application/database");
const response_error_1 = require("../error/response-error");
const product_order_model_1 = require("../model/product-order-model");
const product_order_validation_1 = require("../validation/product-order-validation");
const validation_1 = require("../validation/validation");
class ProductOrderService {
    static create(user, request) {
        return __awaiter(this, void 0, void 0, function* () {
            // Validate the create request
            const createRequest = validation_1.Validation.validate(product_order_validation_1.OrderValidation.CREATE, request);
            // Generate a UUID for the new product order
            const productOrderId = (0, uuid_1.v4)();
            // Insert the new product order into the database with the UUID
            yield database_1.db.query('INSERT INTO product_order (id, user_id, product_id, variation_id, departure, number_of_pax, per_pax_price, total_price) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
                productOrderId,
                user.id,
                createRequest.product_id,
                createRequest.variation_id,
                createRequest.departure,
                createRequest.number_of_pax,
                createRequest.per_pax_price,
                createRequest.total_price,
            ]);
            // Return the UUID of the new product order
            return yield this.get(productOrderId);
        });
    }
    static getAll(queryParams) {
        return __awaiter(this, void 0, void 0, function* () {
            // Validate the query parameters
            const queryRequest = validation_1.Validation.validate(product_order_validation_1.OrderValidation.QUERY, queryParams);
            // Calculate the offset and limit for pagination
            const skip = (queryRequest.page - 1) * queryRequest.limit;
            const limit = queryRequest.limit;
            // Initialize the filter query and parameters
            let filterQuery = '';
            let filterParams = [];
            // If the search query is provided, add the search query to the filter
            if (queryRequest.search) {
                const searchTerm = `%${queryRequest.search.toLowerCase()}%`;
                filterQuery = `
        WHERE LOWER(user.full_name) LIKE ? 
        OR LOWER(user.email) LIKE ? 
        OR LOWER(user.whatsapp_number) LIKE ?
      `;
                filterParams = [searchTerm, searchTerm, searchTerm];
            }
            const sortField = queryRequest.sort || 'created_at';
            const sortOrder = queryRequest.order === 'asc' ? 'ASC' : 'DESC';
            // Build the main query to fetch the product orders
            const productOrders = yield database_1.db.query(`
      SELECT
        po.*,
        JSON_OBJECT(
          'id', user.id,
          'full_name', user.full_name,
          'email', user.email,
          'whatsapp_number', user.whatsapp_number,
          'role', user.role,
          'created_at', user.created_at,
          'updated_at', user.updated_at
        ) AS user,
        JSON_OBJECT(
          'id', IFNULL(pv.id, ''),
          'name', IFNULL(pv.name, ''),
          'price', IFNULL(pv.price, 0)
        ) AS productVariation,
        JSON_OBJECT(
          'name', p.name
        ) AS product
      FROM product_order po
      JOIN user ON po.user_id = user.id
      JOIN product p ON po.product_id = p.id
      LEFT JOIN product_variation pv ON po.variation_id = pv.id
      ${filterQuery}
      ORDER BY ${sortField} ${sortOrder}
      LIMIT ? OFFSET ?
    `, [...filterParams, limit, skip]);
            // Get the total count of product orders matching the filter criteria
            const count = yield database_1.db.queryOne(`
      SELECT COUNT(*) AS total
      FROM product_order po
      JOIN user u ON po.user_id = u.id
      JOIN product p ON po.product_id = p.id
      LEFT JOIN product_variation pv ON po.variation_id = pv.id
      ${filterQuery}
    `, filterParams);
            // If no product orders are found, throw an error
            if (!count) {
                throw new response_error_1.ResponseError(404, 'Produk order tidak ditemukan');
            }
            // Parse the JSON objects from the database
            productOrders.forEach((order) => {
                order.user = JSON.parse(order.user);
                order.productVariation = JSON.parse(order.productVariation);
                order.product = JSON.parse(order.product);
            });
            // Remove the productVariation field if it is empty
            productOrders.forEach((order) => {
                if (order.productVariation && !order.productVariation.id) {
                    order.productVariation = null;
                }
            });
            // Return the pageable response
            return {
                data: productOrders.map(product_order_model_1.toProductOrderResponse),
                pagination: {
                    total: count.total,
                    current_page: queryRequest.page,
                    total_pages: Math.ceil(count.total / queryRequest.limit),
                    limit: queryRequest.limit,
                },
            };
        });
    }
    static getAllByUser(user) {
        return __awaiter(this, void 0, void 0, function* () {
            // Fetch all product orders for the given user
            const productOrders = yield database_1.db.query(`
      SELECT
        po.*,
        JSON_OBJECT(
          'id', u.id,
          'full_name', u.full_name,
          'email', u.email,
          'whatsapp_number', u.whatsapp_number,
          'role', u.role,
          'created_at', u.created_at,
          'updated_at', u.updated_at
        ) AS user,
        JSON_OBJECT(
          'id', pv.id,
          'name', pv.name,
          'price', pv.price
        ) AS productVariation,
        JSON_OBJECT(
          'name', p.name
        ) AS product
      FROM product_order po
      JOIN user u ON po.user_id = u.id
      JOIN product p ON po.product_id = p.id
      LEFT JOIN product_variation pv ON po.variation_id = pv.id
      WHERE u.id = ?
    `, [user.id]);
            // Parse the JSON objects from the database
            productOrders.forEach((order) => {
                order.user = JSON.parse(order.user);
                order.productVariation = JSON.parse(order.productVariation);
                order.product = JSON.parse(order.product);
            });
            // Remove the productVariation field if it is empty
            productOrders.forEach((order) => {
                if (order.productVariation && !order.productVariation.id) {
                    order.productVariation = null;
                }
            });
            // Return the product orders
            return productOrders.map(product_order_model_1.toProductOrderResponse);
        });
    }
    static get(id) {
        return __awaiter(this, void 0, void 0, function* () {
            // Fetch the product order from the database
            const productOrder = yield database_1.db.queryOne(`
        SELECT
          po.*,
          JSON_OBJECT(
            'id', u.id,
            'full_name', u.full_name,
            'email', u.email,
            'whatsapp_number', u.whatsapp_number,
            'role', u.role,
            'created_at', u.created_at,
            'updated_at', u.updated_at
          ) AS user,
           JSON_OBJECT(
            'id', pv.id,
            'name', pv.name,
            'price', pv.price
          ) AS productVariation,
          JSON_OBJECT(
            'name', p.name
          ) AS product
        FROM product_order po
        JOIN user u ON po.user_id = u.id
        JOIN product p ON po.product_id = p.id
        LEFT JOIN product_variation pv ON po.variation_id = pv.id
        WHERE po.id = ?
      `, [id]);
            // If the product order does not exist, throw an error
            if (!productOrder) {
                throw new response_error_1.ResponseError(404, 'Produk order tidak ditemukan');
            }
            // Parse the JSON objects from the database
            productOrder.user = typeof productOrder.user === 'string' ? JSON.parse(productOrder.user) : productOrder.user;
            productOrder.productVariation =
                typeof productOrder.productVariation === 'string'
                    ? JSON.parse(productOrder.productVariation)
                    : productOrder.productVariation;
            productOrder.product =
                typeof productOrder.product === 'string' ? JSON.parse(productOrder.product) : productOrder.product;
            // Remove the productVariation field if it is empty
            if (productOrder.productVariation && !productOrder.productVariation.id) {
                productOrder.productVariation = null;
            }
            // Return the product order response
            return (0, product_order_model_1.toProductOrderResponse)(productOrder);
        });
    }
    static delete(id) {
        return __awaiter(this, void 0, void 0, function* () {
            // Fetch the product order from the database
            const productOrder = yield database_1.db.query(`
      SELECT product_order.id
      FROM product_order
      WHERE product_order.id = ?
    `, [id]);
            // If the product order does not exist, throw an error
            if (productOrder.length === 0) {
                throw new response_error_1.ResponseError(404, 'Produk order tidak ditemukan');
            }
            // Delete the product order from the database
            yield database_1.db.query(`
      DELETE FROM product_order
      WHERE id = ?
    `, [id]);
        });
    }
}
exports.ProductOrderService = ProductOrderService;
