const Leave = require("../models/leaveModel");
const { errorResponse } = require("../utils/errorResponseHandler");
const { logUserAction } = require("../utils/userActionLogger");


const createLeave = async (req, res) => {
    try {
        // const userId = req.user._id;
        const userId = req.session.user.id;
        const orgId = req.user.orgId;

        const {
            leaveType,
            startDate,
            endDate,
            reason,
            isHalfDay = false,
        } = req.body;


        if (!leaveType || !startDate || !endDate) {
            return errorResponse(
                res,
                "Leave type, start date, and end date are required",
                400
            );
        }

        const fromDate = new Date(startDate);
        const toDate = new Date(endDate);

        if (fromDate > toDate) {
            return errorResponse(
                res,
                "Start date cannot be greater than end date",
                400
            );
        }

        /* ================= OPTIONAL: DUPLICATE CHECK ================= */
        // Prevent overlapping leave requests
        // const overlappingLeave = await Leave.findOne({
        //     employee: userId,
        //     orgId,
        //     status: { $in: ["Pending", "Approved"] },
        //     $or: [
        //         { startDate: { $lte: toDate }, endDate: { $gte: fromDate } },
        //     ],
        //     isDeleted: false,
        // });
        // if (overlappingLeave) {
        //     return errorResponse(
        //         res,
        //         "You already have a leave request for the selected dates",
        //         409
        //     );
        // }
        const leave = await Leave.create({
            employee: userId,
            orgId,
            leaveType,
            startDate: fromDate,
            endDate: toDate,
            reason,
            isHalfDay,
            status: "Pending",
            appliedAt: new Date(),
            appliedBy: userId,
        });

        // await logUserAction(req, {
        //     action: "CREATE_LEAVE",
        //     module: "LEAVE",
        //     entityId: leave._id,
        // });

        res.status(201).json({
            success: true,
            message: "Leave request submitted successfully",
            data: leave,
        });
    } catch (error) {
        console.error(error);
        errorResponse(res, "Failed to submit leave request", 500, error);
    }
};



const getLeaves = async (req, res) => {
    try {
        const userId = req.user._id;
        const orgId = req.user.orgId;
        const role = req.user.role;

        let { page = 1, limit = 10 } = req.query;

        page = parseInt(page);
        limit = parseInt(limit);
        const skip = (page - 1) * limit;

        /* ================= BASE FILTER ================= */
        const filter = {
            orgId,
            isDeleted: false,
        };

        /* ================= ROLE BASED FILTER ================= */
        // Employee can see only own leaves
        if (role === "doctor" || role === "employee" || role === "user") {
            filter.employee = userId;
        }

        /* ================= QUERY ================= */
        const [leaves, total] = await Promise.all([
            Leave.find(filter)
                .populate("employee", "firstName lastName")
                .populate("approvedBy", "firstName lastName")
                .sort({ createdAt: -1 })
                .skip(skip)
                .limit(limit),

            Leave.countDocuments(filter),
        ]);

        res.status(200).json({
            success: true,
            message: "Leaves fetched successfully",
            data: leaves,
            pagination: {
                total,
                page,
                limit,
                totalPages: Math.ceil(total / limit),
            },
        });
    } catch (error) {
        console.error(error);
        errorResponse(res, "Failed to fetch leaves", 500, error);
    }
};


const getLeaveById = async (req, res) => {
    try {
        const userId = req.user._id;
        const orgId = req.user.orgId;
        const role = req.user.role;
        const leaveId = req.params.id;

        const filter = {
            _id: leaveId,
            orgId,
            isDeleted: false,
        };

        // Employee can view only own leave
        if (role === "user") {
            filter.employee = userId;
        }

        const leave = await Leave.findOne(filter)
            .populate("employee", "firstName lastName")
            .populate("approvedBy", "firstName lastName");

        if (!leave) {
            return errorResponse(res, "Leave not found", 404);
        }

        // await logUserAction(req, {
        //     userId: req.user.id,
        //     action: "VIEW_LEAVE",
        //     // module: "LEAVE",
        //      model: "Leave",
        //     // entityId: leave._id,
        //     req,
        // });

        res.status(200).json({
            success: true,
            message: "Leave fetched successfully",
            data: leave,
        });
    } catch (error) {
        console.error(error);
        errorResponse(res, "Failed to fetch leave", 500, error);
    }
};


const updateLeave = async (req, res) => {
    try {
        const leaveId = req.params.id;
        const userId = req.user._id;
        const role = req.user.role;

        const leave = await Leave.findById(leaveId);

        if (!leave || leave.isDeleted) {
            return errorResponse(res, "Leave not found", 404);
        }

        /* ================= PERMISSION CHECK ================= */
        // Employee can update only own leave
        if (
            role === "employee" &&
            leave.employee.toString() !== userId.toString()
        ) {
            return errorResponse(res, "Unauthorized to update this leave", 403);
        }

        /* ================= ALLOWED UPDATES ================= */
        const allowedFields = [
            "leaveType",
            "startDate",
            "endDate",
            "reason",
            "status",
            "rejectionReason",
            "isHalfDay",
        ];

        allowedFields.forEach((field) => {
            if (req.body[field] !== undefined) {
                leave[field] = req.body[field];
            }
        });

        /* ================= APPROVAL INFO ================= */
        if (req.body.status && role !== "employee") {
            leave.approvedBy = userId;
            leave.approvedAt = new Date();
        }

        leave.updatedBy = userId;
        await leave.save();

        res.status(200).json({
            success: true,
            message: "Leave updated successfully",
            data: leave,
        });
    } catch (error) {
        console.error(error);
        errorResponse(res, "Failed to update leave", 500, error);
    }
};


const deleteLeave = async (req, res) => {
    try {
        const leaveId = req.params.id;
        const userId = req.user._id;
        const role = req.user.role;

        const leave = await Leave.findById(leaveId);

        if (!leave || leave.isDeleted) {
            return errorResponse(res, "Leave not found", 404);
        }

        /* ================= PERMISSION CHECK ================= */
        // Employee can delete only own leave
        // if (
        //   role === "employee" &&
        //   leave.employee.toString() !== userId.toString()
        // ) {
        //   return errorResponse(res, "Unauthorized to delete this leave", 403);
        // }
        /* ================= SOFT DELETE ================= */

        leave.isDeleted = true;
        leave.updatedBy = userId;

        await leave.save();

        res.status(200).json({
            success: true,
            message: "Leave deleted successfully",
        });
    } catch (error) {
        console.error(error);
        errorResponse(res, "Failed to delete leave", 500, error);
    }
};


module.exports = {
    createLeave,
    getLeaves,
    updateLeave,
    deleteLeave,
    getLeaveById,
};
