const modelProduct = require('../models/product.model');
const { encrypt } = require('../utils/crypto');

class ProductService {
    async createProduct({ title, categoryId, price, description, account, images, info }) {
        const encryptedAccount = {
            username: encrypt(account.username),
            password: encrypt(account.password),
        };
        const product = await modelProduct.create({
            title,
            categoryId,
            price,
            description,
            account: encryptedAccount,
            images,
            info,
        });
        return product;
    }
    async getAllProduct() {
        return await modelProduct.find({});
    }

    async findByTitle(title) {
        return await modelProduct.findOne({ title });
    }

    async updateProduct({ id, title, categoryId, price, description, account, images, oldImages, status, info }) {
        const existingProduct = await modelProduct.findById(id);
        if (!existingProduct) return null;

        let updateData = {
            title,
            categoryId,
            price,
            description,
            status,
            account: { ...existingProduct.account }, // Preserve existing account
            info,
        };

        // Handle Username Update (Re-encrypt if changed)
        if (account.username) {
            updateData.account.username = encrypt(account.username);
        }

        // Handle Password Update (Re-encrypt if changed)
        if (account.password) {
            updateData.account.password = encrypt(account.password);
        }

        // Handle Images
        // oldImages = images user wants to KEEP
        // images = NEW uploaded images
        const currentImages = existingProduct.images || [];

        // Find images to delete (in current but not in oldImages)
        const imagesToDelete = currentImages.filter((img) => !oldImages.includes(img));

        // Delete removed images from disk
        const fs = require('fs');
        const path = require('path');
        imagesToDelete.forEach((img) => {
            const filePath = path.join(__dirname, '../uploads/products', img);
            fs.unlink(filePath, (err) => {
                if (err) console.log('Failed to delete:', img);
            });
        });

        // Final images = kept old images + new uploaded images
        updateData.images = [...oldImages, ...images];

        const product = await modelProduct.findByIdAndUpdate(id, updateData, { new: true });
        return product;
    }

    async deleteProduct(id) {
        const product = await modelProduct.findById(id);
        if (!product) return null;

        product.images.forEach(async (img) => {
            const filePath = path.join(__dirname, '../uploads/products', img);
            await fs.unlink(filePath);
        });

        await modelProduct.findByIdAndDelete(id);
        return true;
    }

    async getProductByCategory(categoryId, { minPrice, maxPrice, sortBy, search, page = 1, limit = 12 }) {
        // Build query
        let query = { categoryId, status: 'available' };

        // Price filter
        if (minPrice || maxPrice) {
            query.price = {};
            if (minPrice) query.price.$gte = Number(minPrice);
            if (maxPrice) query.price.$lte = Number(maxPrice);
        }

        // Search by title
        if (search) {
            query.title = { $regex: search, $options: 'i' };
        }

        // Build sort
        let sort = { createdAt: -1 }; // default: newest first
        if (sortBy === 'price-asc') sort = { price: 1 };
        else if (sortBy === 'price-desc') sort = { price: -1 };
        else if (sortBy === 'newest') sort = { createdAt: -1 };

        // Pagination
        const skip = (Number(page) - 1) * Number(limit);

        // Execute query with pagination
        const [products, total] = await Promise.all([
            modelProduct.find(query).select('-account').sort(sort).skip(skip).limit(Number(limit)),
            modelProduct.countDocuments(query),
        ]);

        return {
            products,
            pagination: {
                page: Number(page),
                limit: Number(limit),
                total,
                totalPages: Math.ceil(total / Number(limit)),
            },
        };
    }

    async getProductById(id) {
        return await modelProduct.findById(id).select('-account');
    }
}
module.exports = new ProductService();
