import { NextRequest, NextResponse } from "next/server";
import dbConnect from "../../src/lib/mongodb";
import Appointment from "../../src/models/appointment";
import Store from "../../src/models/Store";  // ← Add this line
import SLOTS from "../../src/models/Slot";

// 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 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 });
  }
}