import { NextRequest, NextResponse } from "next/server";
import dbConnect from "../lib/mongodb";
import Appointment from "../models/appointment";
import Store from "../models/Store"; // ← Add this line
import SLOTS from "../models/Slot";
import { sendTemplateMail } from "@/lib/email";
import GeneralSettings from "@/models/GeneralSettings";
// export const SLOTS = {
//   "morning": ["10:00 AM", "11:00 AM", "12:00 PM"],
//   "afternoon": ["01:00 PM", "02:00 PM", "03:00 PM"],
//   "evening": ["04:00 PM", "05:00 PM", "06:00 PM"]
// }

// GET /api/appointments
export async function getAppointments(request: NextRequest) {
  try {
    await dbConnect();

    const { searchParams } = new URL(request.url);
    const page = parseInt(searchParams.get("page") || "1");
    const limit = parseInt(searchParams.get("limit") || "10");
    const status = searchParams.get("status");
    const storeId = searchParams.get("storeId");
    const date = searchParams.get("date");
    const search = searchParams.get("search");
    const sort = searchParams.get("sort") || "createdAt";
    const order = searchParams.get("order") || "desc";

    const query: any = {};
    if (status) query.status = status;
    if (storeId) query.storeId = storeId;
    if (date) {
      const d = new Date(date);
      const start = new Date(new Date(d).setHours(0, 0, 0, 0));
      const end = new Date(new Date(d).setHours(23, 59, 59, 999));
      query.date = { $gte: start, $lte: end };
    }
    if (search) {
      query.$or = [
        { name: { $regex: search, $options: "i" } },
        { phone: { $regex: search, $options: "i" } },
        { email: { $regex: search, $options: "i" } },
        { storeName: { $regex: search, $options: "i" } },
      ];
    }

    const sortOptions: any = {};
    sortOptions[sort] = order === "asc" ? 1 : -1;

    const skip = (page - 1) * limit;
    const [appointments, total] = await Promise.all([
      Appointment.find(query)
        .sort(sortOptions)
        .skip(skip)
        .limit(limit)
        .populate("storeId", "name city address") // Now Store model is registered
        .lean(),
      Appointment.countDocuments(query),
    ]);

    return NextResponse.json({
      success: true,
      data: appointments,
      pagination: { page, limit, total, pages: Math.ceil(total / limit) },
    });
  } catch (error: any) {
    console.error("Error in getAppointments:", error); // ← Add this for debugging
    return NextResponse.json(
      { success: false, error: error.message },
      { status: 500 },
    );
  }
}

// POST /api/appointments
export async function createAppointment(request: NextRequest) {
  try {
    await dbConnect();
    const body = await request.json();

    const {
      storeId,
      storeName,
      date,
      timeSlot,
      slotPeriod,
      name,
      phone,
      email,
      celebrating,
      celebratingOther,
      lookingFor,
    } = body;

    // Validate required fields
    if (
      !storeId ||
      !storeName ||
      !date ||
      !timeSlot ||
      !slotPeriod ||
      !name ||
      !phone ||
      !email ||
      !celebrating
    ) {
      return NextResponse.json(
        { success: false, error: "All required fields must be filled" },
        { status: 400 },
      );
    }

    // Validate slot period
    if (!Object.keys(SLOTS).includes(slotPeriod)) {
      return NextResponse.json(
        { success: false, error: "Invalid slot period" },
        { status: 400 },
      );
    }

    // Validate timeSlot belongs to slotPeriod
    if (!SLOTS[slotPeriod as keyof typeof SLOTS].includes(timeSlot)) {
      return NextResponse.json(
        { success: false, error: "Invalid time slot for selected period" },
        { status: 400 },
      );
    }

    // Check if slot already booked
    const d = new Date(date);
    const start = new Date(new Date(d).setHours(0, 0, 0, 0));
    const end = new Date(new Date(d).setHours(23, 59, 59, 999));

    const existing = await Appointment.findOne({
      storeId,
      date: { $gte: start, $lte: end },
      timeSlot,
      status: { $nin: ["cancelled"] },
    });

    if (existing) {
      return NextResponse.json(
        {
          success: false,
          error: "This slot is already booked. Please choose another.",
        },
        { status: 409 },
      );
    }
    const admindetails = await GeneralSettings.findOne();
    try {
      await sendTemplateMail({
        slug: "appointment",
        to: email,
        replyTo: email,
        templateData: { name, email, phone },
      });
      await sendTemplateMail({
        slug: "admin-appointment",
        to: admindetails.email,
        replyTo: admindetails.email,
        templateData: { name, email, phone },
      });
    } catch (err: any) {
      console.error("Contact notification email failed", err);
    }
    const appointment = await Appointment.create({
      storeId,
      storeName,
      date: new Date(date),
      timeSlot,
      slotPeriod,
      name,
      phone,
      email,
      celebrating,
      celebratingOther,
      lookingFor,
      status: "pending",
    });

    return NextResponse.json(
      { success: true, data: appointment },
      { status: 201 },
    );
  } catch (error: any) {
    console.error("Error in createAppointment:", error); // ← Add this for debugging
    return NextResponse.json(
      { success: false, error: error.message },
      { status: 500 },
    );
  }
}

// GET /api/appointments/:id
export async function getAppointmentById(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> },
) {
  try {
    await dbConnect();
    const { id } = await params;
    const appointment = await Appointment.findById(id).populate(
      "storeId",
      "name city address phone",
    ); // Also needs Store model

    if (!appointment) {
      return NextResponse.json(
        { success: false, error: "Appointment not found" },
        { status: 404 },
      );
    }

    return NextResponse.json({ success: true, data: appointment });
  } catch (error: any) {
    console.error("Error in getAppointmentById:", error); // ← Add this for debugging
    return NextResponse.json(
      { success: false, error: error.message },
      { status: 500 },
    );
  }
}

// PUT /api/appointments/:id
export async function updateAppointment(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> },
) {
  try {
    await dbConnect();
    const { id } = await params;
    const body = await request.json();

    const allowedFields = ["status", "date", "timeSlot", "slotPeriod"];
    const updateData: any = {};
    allowedFields.forEach((field) => {
      if (body[field] !== undefined) updateData[field] = body[field];
    });

    const appointment = await Appointment.findByIdAndUpdate(
      id,
      { $set: updateData },
      { new: true, runValidators: true },
    );

    if (!appointment) {
      return NextResponse.json(
        { success: false, error: "Appointment not found" },
        { status: 404 },
      );
    }

    return NextResponse.json({ success: true, data: appointment });
  } catch (error: any) {
    console.error("Error in updateAppointment:", error); // ← Add this for debugging
    return NextResponse.json(
      { success: false, error: error.message },
      { status: 500 },
    );
  }
}

// DELETE /api/appointments/:id
export async function deleteAppointment(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> },
) {
  try {
    await dbConnect();
    const { id } = await params;
    const appointment = await Appointment.findByIdAndDelete(id);

    if (!appointment) {
      return NextResponse.json(
        { success: false, error: "Appointment not found" },
        { status: 404 },
      );
    }

    return NextResponse.json({
      success: true,
      message: "Appointment deleted successfully",
    });
  } catch (error: any) {
    console.error("Error in deleteAppointment:", error); // ← Add this for debugging
    return NextResponse.json(
      { success: false, error: error.message },
      { status: 500 },
    );
  }
}

// GET /api/appointments/slots?storeId=&date=
export async function getAvailableSlots(request: NextRequest) {
  try {
    await dbConnect();

    const { searchParams } = new URL(request.url);
    const storeId = searchParams.get("storeId");
    const date = searchParams.get("date");

    if (!storeId || !date) {
      return NextResponse.json(
        { success: false, error: "storeId and date are required" },
        { status: 400 },
      );
    }

    const d = new Date(date);
    const start = new Date(new Date(d).setHours(0, 0, 0, 0));
    const end = new Date(new Date(d).setHours(23, 59, 59, 999));

    const booked = await Appointment.find({
      storeId,
      date: { $gte: start, $lte: end },
      status: { $nin: ["cancelled"] },
    })
      .select("timeSlot slotPeriod")
      .lean();

    const bookedTimes = booked.map((a: any) => a.timeSlot);

    const availability: Record<string, { time: string; available: boolean }[]> =
      {};
    Object.entries(SLOTS).forEach(([period, times]) => {
      availability[period] = times.map((time) => ({
        time,
        available: !bookedTimes.includes(time),
      }));
    });

    return NextResponse.json({ success: true, data: availability });
  } catch (error: any) {
    console.error("Error in getAvailableSlots:", error); // ← Add this for debugging
    return NextResponse.json(
      { success: false, error: error.message },
      { status: 500 },
    );
  }
}
