const Discount = require('../models/discount.model');
const { BadRequestError, NotFoundError } = require('../core/error.response');

class DiscountService {
    // Admin: Tạo mã giảm giá
    async createDiscount(data) {
        const existingCode = await Discount.findOne({ code: data.code.toUpperCase() });
        if (existingCode) {
            throw new BadRequestError('Mã giảm giá đã tồn tại!');
        }
        const discount = await Discount.create({
            ...data,
            code: data.code.toUpperCase(),
        });
        return discount;
    }

    // Admin: Lấy tất cả mã
    async getAllDiscounts() {
        return await Discount.find().sort({ createdAt: -1 });
    }

    // Admin: Cập nhật mã
    async updateDiscount(id, data) {
        const discount = await Discount.findById(id);
        if (!discount) {
            throw new NotFoundError('Không tìm thấy mã giảm giá!');
        }

        if (data.code && data.code.toUpperCase() !== discount.code) {
            const existingCode = await Discount.findOne({ code: data.code.toUpperCase() });
            if (existingCode) {
                throw new BadRequestError('Mã giảm giá đã tồn tại!');
            }
            data.code = data.code.toUpperCase();
        }

        Object.assign(discount, data);
        await discount.save();
        return discount;
    }

    // Admin: Xóa mã
    async deleteDiscount(id) {
        const discount = await Discount.findByIdAndDelete(id);
        if (!discount) {
            throw new NotFoundError('Không tìm thấy mã giảm giá!');
        }
        return discount;
    }

    // User: Kiểm tra và áp dụng mã
    async validateAndApplyDiscount(code, userId, orderTotal) {
        const discount = await Discount.findOne({ code: code.toUpperCase() });

        if (!discount) {
            throw new BadRequestError('Mã giảm giá không tồn tại!');
        }

        // Kiểm tra trạng thái
        if (!discount.isActive) {
            throw new BadRequestError('Mã giảm giá đã bị vô hiệu hóa!');
        }

        // Kiểm tra thời hạn
        const now = new Date();
        if (now < discount.startDate) {
            throw new BadRequestError('Mã giảm giá chưa có hiệu lực!');
        }
        if (now > discount.endDate) {
            throw new BadRequestError('Mã giảm giá đã hết hạn!');
        }

        // Kiểm tra giới hạn sử dụng tổng
        if (discount.usageLimit !== null && discount.usedCount >= discount.usageLimit) {
            throw new BadRequestError('Mã giảm giá đã hết lượt sử dụng!');
        }

        // Kiểm tra user đã dùng chưa
        const userUsageCount = discount.usedByUsers.filter((uid) => uid.toString() === userId.toString()).length;
        if (userUsageCount >= discount.userLimit) {
            throw new BadRequestError('Bạn đã sử dụng mã giảm giá này rồi!');
        }

        // Kiểm tra đơn hàng tối thiểu
        if (orderTotal < discount.minOrderValue) {
            throw new BadRequestError(
                `Đơn hàng tối thiểu ${discount.minOrderValue.toLocaleString('vi-VN')}đ để sử dụng mã này!`,
            );
        }

        // Tính số tiền giảm
        let discountAmount = 0;
        if (discount.type === 'percentage') {
            discountAmount = Math.floor((orderTotal * discount.value) / 100);
            // Áp dụng giới hạn maxDiscountValue
            if (discount.maxDiscountValue !== null && discountAmount > discount.maxDiscountValue) {
                discountAmount = discount.maxDiscountValue;
            }
        } else {
            // fixed_amount
            discountAmount = discount.value;
        }

        // Không giảm quá giá trị đơn hàng
        if (discountAmount > orderTotal) {
            discountAmount = orderTotal;
        }

        return {
            discountId: discount._id,
            code: discount.code,
            type: discount.type,
            value: discount.value,
            discountAmount,
            finalPrice: orderTotal - discountAmount,
        };
    }

    // Cập nhật usage sau khi mua thành công
    async markAsUsed(discountId, userId) {
        await Discount.findByIdAndUpdate(discountId, {
            $inc: { usedCount: 1 },
            $push: { usedByUsers: userId },
        });
    }
}

module.exports = new DiscountService();
