const Customer = require('../models/customerSchema');
const Tenant = require('../models/tenantSchema');
const AuditLog = require('../models/auditLogSchema');
const mongoose = require('mongoose');

const createCustomer = async (req, res) => {
    try {
        const { tenantId, caseNo, name, mobile, dob, gender, kycStatus } = req.body;

        // Validate tenant exists
        const tenant = await Tenant.findById(tenantId);
        if (!tenant || !tenant.isActive) {
            return res.status(400).json({
                error: 'Invalid or inactive tenant',
                code: 'INVALID_TENANT'
            });
        }

        // Check if customer with same caseNo exists for this tenant
        const existingCustomer = await Customer.findOne({ tenantId, caseNo });
        if (existingCustomer) {
            return res.status(409).json({
                error: 'Customer with this case number already exists for this tenant',
                code: 'DUPLICATE_CASE_NUMBER'
            });
        }

        // Create customer
        const customer = new Customer({
            tenantId,
            caseNo: caseNo.trim(),
            name: name.trim(),
            mobile: mobile.trim(),
            dob: dob || null,
            gender: gender || null,
            kycStatus: kycStatus || 'pending',
            createdBy: req.user._id
        });

        await customer.save();

        // Populate the created customer
        const populatedCustomer = await Customer.findById(customer._id)
            .populate('tenantId', 'name code')
            .populate('createdBy', 'name email');

        // Log the action
        await AuditLog.create({
            userId: req.user._id,
            action: 'customer_created',
            ipAddress: req.ip,
        });

        res.status(201).json({
            message: 'Customer created successfully',
            customer: populatedCustomer
        });
    } catch (error) {
        console.error('Create customer error:', error);
        res.status(500).json({
            error: 'Internal server error',
            code: 'CREATE_CUSTOMER_FAILED'
        });
    }
}

const getAllCustomers = async (req, res) => {
    try {
        const {
            tenantId,
            kycStatus,
            page = 1,
            limit = 10,
            sortBy = 'createdAt',
            sortOrder = 'desc',
            search
        } = req.query;

        // Build filter
        let filter = {};

        if (tenantId) {
            filter.tenantId = tenantId;
        }

        if (kycStatus) {
            filter.kycStatus = kycStatus;
        }

        if (search) {
            filter.$or = [
                { name: { $regex: search, $options: 'i' } },
                { caseNo: { $regex: search, $options: 'i' } },
                { mobile: { $regex: search, $options: 'i' } }
            ];
        }

        // Build sort
        const sort = {};
        sort[sortBy] = sortOrder === 'desc' ? -1 : 1;

        // Execute query
        const customers = await Customer.find(filter)
            .populate('tenantId', 'name code')
            .populate('createdBy', 'name email')
            .sort(sort)
            .limit(limit * 1)
            .skip((page - 1) * limit);

        const total = await Customer.countDocuments(filter);

        res.status(200).json({
            customers,
            pagination: {
                currentPage: parseInt(page),
                totalPages: Math.ceil(total / limit),
                totalRecords: total,
                limit: parseInt(limit)
            }
        });
    } catch (error) {
        console.error('Get customers error:', error);
        res.status(500).json({
            error: 'Internal server error',
            code: 'GET_CUSTOMERS_FAILED'
        });
    }
}

const getCustomerById = async (req, res) => {
    try {
        const { id } = req.params;

        if (!mongoose.Types.ObjectId.isValid(id)) {
            return res.status(400).json({
                error: 'Invalid customer ID format',
                code: 'INVALID_CUSTOMER_ID'
            });
        }

        const customer = await Customer.findById(id)
            .populate('tenantId', 'name code')
            .populate('createdBy', 'name email');

        if (!customer) {
            return res.status(404).json({
                error: 'Customer not found',
                code: 'CUSTOMER_NOT_FOUND'
            });
        }

        res.status(200).json({
            customer,
            message: 'Customer retrieved successfully'
        });
    } catch (error) {
        console.error('Get customer by ID error:', error);
        res.status(500).json({
            error: 'Internal server error',
            code: 'GET_CUSTOMER_FAILED'
        });
    }
}

const updateCustomer = async (req, res) => {
    try {
        const { id } = req.params;
        const { tenantId, caseNo, name, mobile, dob, gender, kycStatus } = req.body;

        if (!mongoose.Types.ObjectId.isValid(id)) {
            return res.status(400).json({
                error: 'Invalid customer ID format',
                code: 'INVALID_CUSTOMER_ID'
            });
        }

        const customer = await Customer.findById(id);
        if (!customer) {
            return res.status(404).json({
                error: 'Customer not found',
                code: 'CUSTOMER_NOT_FOUND'
            });
        }

        // Check if caseNo is being changed and validate uniqueness
        if ((tenantId && tenantId !== customer?.tenantId?.toString()) ||
            (caseNo && caseNo !== customer.caseNo)) {
            const existingCustomer = await Customer.findOne({
                tenantId: tenantId || customer.tenantId,
                caseNo: caseNo || customer.caseNo,
                _id: { $ne: id }
            });
            if (existingCustomer) {
                return res.status(409).json({
                    error: 'Customer with this case number already exists for this tenant',
                    code: 'DUPLICATE_CASE_NUMBER'
                });
            }
        }

        // Validate tenant if being changed
        if (tenantId && tenantId !== customer.tenantId.toString()) {
            const tenant = await Tenant.findById(tenantId);
            if (!tenant || !tenant.isActive) {
                return res.status(400).json({
                    error: 'Invalid or inactive tenant',
                    code: 'INVALID_TENANT'
                });
            }
            customer.tenantId = tenantId;
        }

        // Update fields
        if (caseNo !== undefined) customer.caseNo = caseNo.trim();
        if (name !== undefined) customer.name = name.trim();
        if (mobile !== undefined) customer.mobile = mobile.trim();
        if (dob !== undefined) customer.dob = dob;
        if (gender !== undefined) customer.gender = gender;
        if (kycStatus !== undefined) customer.kycStatus = kycStatus;

        await customer.save();

        // Get updated customer with populated fields
        const updatedCustomer = await Customer.findById(id)
            .populate('tenantId', 'name code')
            .populate('createdBy', 'name email');

        // Log the action
        await AuditLog.create({
            userId: req.user._id,
            action: 'customer_updated',
            ipAddress: req.ip,
        });

        res.status(200).json({
            message: 'Customer updated successfully',
            customer: updatedCustomer
        });
    } catch (error) {
        console.error('Update customer error:', error);
        res.status(500).json({
            error: 'Internal server error',
            code: 'UPDATE_CUSTOMER_FAILED'
        });
    }
}

const deleteCustomer = async (req, res) => {
    try {
        const { id } = req.params;

        if (!mongoose.Types.ObjectId.isValid(id)) {
            return res.status(400).json({
                error: 'Invalid customer ID format',
                code: 'INVALID_CUSTOMER_ID'
            });
        }

        const customer = await Customer.findById(id);
        if (!customer) {
            return res.status(404).json({
                error: 'Customer not found',
                code: 'CUSTOMER_NOT_FOUND'
            });
        }

        // Store customer data for audit before deletion
        await Customer.findByIdAndDelete(id);

        // Log the action
        await AuditLog.create({
            userId: req.user._id,
            action: 'customer_deleted',
            ipAddress: req.ip,
        });

        res.status(200).json({
            message: 'Customer deleted successfully'
        });
    } catch (error) {
        console.error('Delete customer error:', error);
        res.status(500).json({
            error: 'Internal server error',
            code: 'DELETE_CUSTOMER_FAILED'
        });
    }
}

const getCustomersByTenant = async (req, res) => {
    try {
        const { tenantId } = req.params;
        const { kycStatus, page = 1, limit = 10 } = req.query;

        if (!mongoose.Types.ObjectId.isValid(tenantId)) {
            return res.status(400).json({
                error: 'Invalid tenant ID format',
                code: 'INVALID_TENANT_ID'
            });
        }

        let filter = { tenantId };
        if (kycStatus) {
            filter.kycStatus = kycStatus;
        }

        const customers = await Customer.find(filter)
            .populate('tenantId', 'name code')
            .populate('createdBy', 'name email')
            .sort({ createdAt: -1 })
            .limit(limit * 1)
            .skip((page - 1) * limit);

        const total = await Customer.countDocuments(filter);

        res.status(200).json({
            customers,
            pagination: {
                currentPage: parseInt(page),
                totalPages: Math.ceil(total / limit),
                totalRecords: total,
                limit: parseInt(limit)
            }
        });
    } catch (error) {
        console.error('Get customers by tenant error:', error);
        res.status(500).json({
            error: 'Internal server error',
            code: 'GET_TENANT_CUSTOMERS_FAILED'
        });
    }
}

module.exports = {
    createCustomer,
    getAllCustomers,
    getCustomerById,
    updateCustomer,
    deleteCustomer,
    getCustomersByTenant
};