
import { Request, Response } from 'express';
import { ComplianceDoc } from '../models/ComplianceDoc';
import { HSEIncident, RiskAssessment } from '../models/ComplianceHSE';
import { findProjectByIdOrCode } from '../utils/projectHelper';
import { createComplianceExpiryAlert } from '../services/alertService';
import mongoose from 'mongoose';

export const getComplianceDocs = async (req: Request, res: Response) => {
    try {
        const { siteId } = req.query; // Matches "siteId" from frontend request

        if (!siteId) {
            return res.status(400).json({ success: false, message: 'siteId (projectId) is required' });
        }

        const projectId = siteId as string;
        let projectObjectId: any;

        // Check if projectId is a valid MongoDB ObjectId
        if (mongoose.Types.ObjectId.isValid(projectId)) {
            projectObjectId = new mongoose.Types.ObjectId(projectId);
        } else {
            // Use helper function to find project without Mongoose casting errors
            const project = await findProjectByIdOrCode(projectId);
            if (!project) {
                return res.status(404).json({ success: false, message: `Project with ID or code "${projectId}" not found` });
            }
            projectObjectId = project._id;
        }

        let docs;
        // Use native MongoDB query if projectObjectId is a string to avoid ObjectId casting
        if (typeof projectObjectId === 'string' && !mongoose.Types.ObjectId.isValid(projectObjectId)) {
            if (!mongoose.connection.db) {
                throw new Error('Database connection not established');
            }
            const collection = mongoose.connection.db.collection('compliancedocs'); // Mongoose pluralizes to lowercase by default
            docs = await collection.find({ projectId: projectObjectId }).toArray();
        } else {
            docs = await ComplianceDoc.find({ projectId: projectObjectId });
        }

        res.json({
            success: true,
            data: docs
        });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};

export const getHSEIncidents = async (req: Request, res: Response) => {
    try {
        const { siteId } = req.query;

        if (!siteId) {
            return res.status(400).json({ success: false, message: 'siteId (projectId) is required' });
        }

        const projectId = siteId as string;
        let projectObjectId: any;

        if (mongoose.Types.ObjectId.isValid(projectId)) {
            projectObjectId = new mongoose.Types.ObjectId(projectId);
        } else {
            const project = await findProjectByIdOrCode(projectId);
            if (!project) {
                return res.status(404).json({ success: false, message: `Project with ID or code "${projectId}" not found` });
            }
            projectObjectId = project._id;
        }

        let incidents;
        if (typeof projectObjectId === 'string' && !mongoose.Types.ObjectId.isValid(projectObjectId)) {
            if (!mongoose.connection.db) {
                throw new Error('Database connection not established');
            }
            const collection = mongoose.connection.db.collection('hseincidents');
            incidents = await collection.find({ projectId: projectObjectId }).toArray();
        } else {
            incidents = await HSEIncident.find({ projectId: projectObjectId });
        }

        res.json({ success: true, data: incidents });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};

export const getRisks = async (req: Request, res: Response) => {
    try {
        // Risks are usually global or system-wide, but if project-specific logic is needed, add it here.
        // For now returning all risks as per frontend call structure (no args)
        const risks = await RiskAssessment.find({}).sort({ createdAt: -1 });
        res.json({ success: true, data: risks });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};

export const createComplianceDoc = async (req: Request, res: Response) => {
    try {
        const { siteId, ...docData } = req.body;

        if (!siteId) {
            return res.status(400).json({ success: false, message: 'siteId (projectId) is required' });
        }

        const projectId = siteId as string;
        let projectObjectId: any;

        if (mongoose.Types.ObjectId.isValid(projectId)) {
            projectObjectId = new mongoose.Types.ObjectId(projectId);
        } else {
            const project = await findProjectByIdOrCode(projectId);
            if (!project) {
                return res.status(404).json({ success: false, message: `Project with ID or code "${projectId}" not found` });
            }
            projectObjectId = project._id;
        }

        const newDoc = new ComplianceDoc({
            ...docData,
            projectId: projectObjectId
        });

        await newDoc.save();

        // Create alert if document is expiring soon
        if (newDoc.expiryDate) {
            const expiryDate = new Date(newDoc.expiryDate);
            const now = new Date();
            const daysUntilExpiry = Math.ceil((expiryDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
            
            if (daysUntilExpiry <= 30) {
                await createComplianceExpiryAlert(
                    newDoc.name,
                    newDoc._id.toString(),
                    daysUntilExpiry
                );
            }
        }

        res.status(201).json({ success: true, data: newDoc });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};

export const updateComplianceDoc = async (req: Request, res: Response) => {
    try {
        const { id } = req.params;
        const updateData = req.body;

        const updatedDoc = await ComplianceDoc.findByIdAndUpdate(id, updateData, { new: true });

        if (!updatedDoc) {
            return res.status(404).json({ success: false, message: 'Document not found' });
        }

        // Create alert if document is expiring soon
        if (updatedDoc.expiryDate) {
            const expiryDate = new Date(updatedDoc.expiryDate);
            const now = new Date();
            const daysUntilExpiry = Math.ceil((expiryDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
            
            if (daysUntilExpiry <= 30) {
                await createComplianceExpiryAlert(
                    updatedDoc.name,
                    updatedDoc._id.toString(),
                    daysUntilExpiry
                );
            }
        }

        res.json({ success: true, data: updatedDoc });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};

export const deleteComplianceDoc = async (req: Request, res: Response) => {
    try {
        const { id } = req.params;

        const deletedDoc = await ComplianceDoc.findByIdAndDelete(id);

        if (!deletedDoc) {
            return res.status(404).json({ success: false, message: 'Document not found' });
        }

        res.json({ success: true, message: 'Document deleted successfully' });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};

export const createHSEIncident = async (req: Request, res: Response) => {
    try {
        const { siteId, ...incidentData } = req.body;

        if (!siteId) {
            return res.status(400).json({ success: false, message: 'siteId (projectId) is required' });
        }

        const projectId = siteId as string;
        let projectObjectId: any;

        if (mongoose.Types.ObjectId.isValid(projectId)) {
            projectObjectId = new mongoose.Types.ObjectId(projectId);
        } else {
            const project = await findProjectByIdOrCode(projectId);
            if (!project) {
                return res.status(404).json({ success: false, message: `Project with ID or code "${projectId}" not found` });
            }
            projectObjectId = project._id;
        }

        const newIncident = new HSEIncident({
            ...incidentData,
            projectId: projectObjectId
        });

        await newIncident.save();

        res.status(201).json({ success: true, data: newIncident });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};

export const updateHSEIncident = async (req: Request, res: Response) => {
    try {
        const { id } = req.params;
        const updateData = req.body;

        const updatedIncident = await HSEIncident.findByIdAndUpdate(id, updateData, { new: true });

        if (!updatedIncident) {
            return res.status(404).json({ success: false, message: 'Incident not found' });
        }

        res.json({ success: true, data: updatedIncident });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};

export const deleteHSEIncident = async (req: Request, res: Response) => {
    try {
        const { id } = req.params;

        const deletedIncident = await HSEIncident.findByIdAndDelete(id);

        if (!deletedIncident) {
            return res.status(404).json({ success: false, message: 'Incident not found' });
        }

        res.json({ success: true, message: 'Incident deleted successfully' });
    } catch (error: any) {
        res.status(500).json({ success: false, message: error.message });
    }
};
