const Slot = require("../models/slotModel");
const { errorResponse } = require("../utils/errorResponseHandler");
const { logUserAction } = require("../utils/userActionLogger");
const generateSlots = require("../utils/slotGenerator");
const User = require("../models/userModel");
const { getDoctorLeaveForDate } = require("../utils/doctorAvailability");

// const getDoctorSlots = async (req, res) => {
//     try {
//         const { doctorId } = req.params;
//         const { date, duration } = req.query;
//         const orgId = req.user.orgId;

//         /*  BASIC VALIDATION */
//         // if (!date) {
//         //   return errorResponse(res, "Date is required", 400);
//         // }

//         /*  CHECK DOCTOR */
//         const doctor = await User.findOne({
//             _id: doctorId,
//             role: "doctor",
//             orgId,
//             isDeleted: false,
//         });

//         if (!doctor) {
//             return errorResponse(res, "Doctor not found", 404);
//         }

//         /*  CHECK EXISTING SLOTS */
//         let slots = await Slot.find({
//             doctor: doctorId,
//             date,
//             duration: Number(duration),
//             orgId,
//             // isDeleted: false,
//         }).sort({ startTime: 1 });

//         /* GENERATE SLOTS IF NOT EXISTS */
//         if (slots.length === 0) {
//             const generatedSlots = generateSlots({
//                 start: doctor.workingHours.start,
//                 end: doctor.workingHours.end,
//                 lunchStart: doctor.lunchBreak?.start,
//                 lunchEnd: doctor.lunchBreak?.end,
//                 // duration: doctor.slotDuration || 15,
//                 duration: Number(duration),
//             });

//             const slotDocs = generatedSlots.map((slot) => ({
//                 doctor: doctorId,
//                 date,
//                 duration: Number(duration),
//                 startTime: slot.startTime,
//                 endTime: slot.endTime,
//                 orgId,
//                 createdBy: req.user._id,
//             }));

//             slots = await Slot.insertMany(slotDocs);
//         }

//         const now = new Date();
//         const today = now.toISOString().split("T")[0]; // YYYY-MM-DD
//         const currentMinutes = now.getHours() * 60 + now.getMinutes();
//         const updatedSlots = slots.map((slot) => {
//             let isDisabled = false;

//             // Apply only if selected date is today
//             if (date === today) {
//                 const [h, m] = slot.startTime.split(":").map(Number);
//                 const slotMinutes = h * 60 + m;

//                 if (slotMinutes < currentMinutes) {
//                     isDisabled = true;
//                 }
//             }

//             return {
//                 ...slot.toObject(),
//                 isDisabled,
//             };
//         });


//         /*  LOG ACTION (OPTIONAL BUT GOOD) */
//         // logUserAction(req, "FETCH_DOCTOR_SLOTS", {
//         //     doctorId,
//         //     date,
//         // });

//         return res.status(200).json({
//             success: true,
//             count: slots.length,
//             // data: slots,
//             data: updatedSlots,
//         });
//     } catch (error) {
//         console.error("getDoctorSlots error:", error);
//         return errorResponse(res, "Failed to fetch doctor slots", 500);
//     }
// };


// const bookSlot = async (req, res) => {
//   try {
//     const { slotId } = req.body;
//     const userId = req.user._id;

//     const slot = await Slot.findById(slotId);

//     if (!slot) {
//       return errorResponse(res, "Slot not found", 404);
//     }

//     if (slot.isBooked) {
//       return res.status(409).json({
//         success: false,
//         message: "This slot is already booked by another user",
//       });
//     }

//     slot.isBooked = true;
//     slot.bookedBy = userId;

//     await slot.save();

//     return res.status(200).json({
//       success: true,
//       message: "Slot booked successfully",
//     });
//   } catch (err) {
//     console.error(err);
//     return errorResponse(res, "Failed to book slot", 500);
//   }
// };

const getDoctorSlots = async (req, res) => {
    try {
        const { doctorId } = req.params;
        const { duration } = req.query;
        const orgId = req.user?.orgId || req.query.orgId || req.body.orgId;
        // const orgId = req.user.orgId;

        if (!duration) {
            return errorResponse(res, "Date and duration are required", 400);
        }

        const doctor = await User.findOne({
            _id: doctorId,
            role: "doctor",
            orgId,
            isDeleted: false,
        });

        if (!doctor) {
            return errorResponse(res, "Doctor not found", 404);
        }

        // const leave = await getDoctorLeaveForDate(doctorId, date, orgId);
        // console.log(leave);

        // if (leave) {
        //     return res.status(200).json({
        //         success: true,
        //         doctorOnLeave: true,
        //         message: "Doctor is on leave for this date",
        //         slotId: null,
        //         data: [],  // No slots
        //     });
        // }

        // Find single document

        let slotDoc = await Slot.findOne({
            doctor: doctorId,
            // date,
            // duration: Number(duration),
            orgId,
        });

        const generatedSlots = generateSlots({
            start: doctor.workingHours.start,
            end: doctor.workingHours.end,
            lunchStart: doctor.lunchBreak?.start,
            lunchEnd: doctor.lunchBreak?.end,
            duration: Number(duration),
        });

        // If not exists, create once
        if (!slotDoc) {
            slotDoc = await Slot.create({
                doctor: doctorId,
                // date,
                duration: Number(duration),
                orgId,
                slots: generatedSlots, // IMPORTANT
            });
        }
        else {
            // Update existing document
            slotDoc.duration = duration;
            slotDoc.slots = generatedSlots;
            await slotDoc.save();
        }


        //  Disable past slots (today logic)
        // const now = new Date();
        // const today = now.toISOString().split("T")[0];
        // const currentMinutes = now.getHours() * 60 + now.getMinutes();

        // const updatedSlots = slotDoc.slots.map((slot) => {
        //     let isDisabled = false;

        //     if (date === today) {
        //         const [h, m] = slot.startTime.split(":").map(Number);
        //         const slotMinutes = h * 60 + m;

        //         if (slotMinutes < currentMinutes) {
        //             isDisabled = true;
        //         }
        //     }

        //     return {
        //         ...slot.toObject(),
        //         isDisabled,
        //     };
        // });

        return res.status(200).json({
            success: true,
            slotId: slotDoc._id,
            data: slotDoc.slots,
        });
    } catch (error) {
        console.error("getDoctorSlots error:", error);
        return errorResponse(res, "Failed to fetch doctor slots", 500);
    }
};


const bookSlot = async (req, res) => {
    try {
        const { slotId, startTime } = req.body;
        const userId = req.user._id;

        const slot = await Slot.findOneAndUpdate(
            {
                _id: slotId,
                slots: {
                    $elemMatch: {
                        startTime: startTime,
                        isBooked: false,
                    },
                },
            },
            {
                $set: {
                    "slots.$.isBooked": true,
                    "slots.$.bookedBy": userId,
                },
            },
            { new: true }
        );

        if (!slot) {
            return res.status(409).json({
                success: false,
                message: "This slot is already booked by another user",
            });
        }

        return res.status(200).json({
            success: true,
            message: "Slot booked successfully..",
        });
    } catch (err) {
        console.error(err);
        return errorResponse(res, "Failed to book slot", 500);
    }
};

const getAppointmentSlots = async (req, res) => {
  try {
    const { doctorId } = req.params;
    const { date } = req.query;
    const orgId = req.user?.orgId;

    if (!doctorId || !date) {
      return errorResponse(res, "Doctor ID and date are required", 400);
    }

    /* ================= DOCTOR VALIDATION ================= */

    const doctor = await User.findOne({
      _id: doctorId,
      role: "doctor",
      orgId,
      isDeleted: false,
    }).select("_id");

    if (!doctor) {
      return errorResponse(res, "Doctor not found", 404);
    }

    /* ================= CHECK DOCTOR LEAVE ================= */

    const leave = await getDoctorLeaveForDate(doctorId, date, orgId);

    if (leave) {
      return res.status(200).json({
        success: true,
        doctorOnLeave: true,
        message: "Doctor is on leave for this date",
        slotId: null,
        data: [],
      });
    }

    /* ================= FETCH EXISTING SLOT DOC ================= */

    const slotDoc = await Slot.findOne({
      doctor: doctorId,
    //   date,
      orgId,
    });

    if (!slotDoc) {
      return res.status(200).json({
        success: true,
        doctorOnLeave: false,
        slotId: null,
        data: [],
      });
    }

    /* ================= DISABLE PAST TIME LOGIC ================= */

    const now = new Date();
    const today = now.toISOString().split("T")[0];
    const currentMinutes = now.getHours() * 60 + now.getMinutes();

    const updatedSlots = slotDoc.slots.map((slot) => {
      let isDisabled = slot.isDisabled || false;

      if (date === today) {
        const [h, m] = slot.startTime.split(":").map(Number);
        const slotMinutes = h * 60 + m;

        if (slotMinutes <= currentMinutes) {
          isDisabled = true;
        }
      }

      return {
        ...slot.toObject(),
        isDisabled,
      };
    });

    /* ================= RESPONSE ================= */

    return res.status(200).json({
      success: true,
      doctorOnLeave: false,
      slotId: slotDoc._id,
      data: updatedSlots,
    });

  } catch (error) {
    console.error("getAppointmentSlots error:", error);
    return errorResponse(res, "Failed to fetch doctor slots", 500);
  }
};



module.exports = {
    getDoctorSlots,
    bookSlot,
    getAppointmentSlots,
}