import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/infrastructure/db/prisma";
import { checkRateLimit } from "@/lib/rate-limiter";
import {
  CreateEventRequest,
  createEvent,
  formatPhoneNumber,
} from "@/infrastructure/external/calendar";

export async function POST(request: NextRequest) {
  try {
    const body = (await request.json()) as CreateEventRequest;

    // Validate required fields
    if (!body.summary || !body.start || !body.patientPhone || !body.patientName) {
      return NextResponse.json(
        { error: "Summary, start date, patient phone and patient name are required" },
        { status: 400 }
      );
    }

    const startDate = new Date(body.start);

    // Validate date
    if (isNaN(startDate.getTime())) {
      return NextResponse.json({ error: "Invalid date format" }, { status: 400 });
    }

    // Validate phone number
    const phone = formatPhoneNumber(body.patientPhone);
    if (phone.length < 10) {
      return NextResponse.json({ error: "Invalid phone number format" }, { status: 400 });
    }

    // Validate name
    if (body.patientName.trim().length < 2) {
      return NextResponse.json(
        { error: "Patient name must be at least 2 characters" },
        { status: 400 }
      );
    }

    const ip =
      request.ip ||
      request.headers.get("x-forwarded-for")?.split(",")[0] ||
      request.headers.get("x-real-ip") ||
      "unknown";

    // Check rate limit by IP
    const ipLimit = await checkRateLimit(ip, "ip");
    if (!ipLimit.success) {
      return NextResponse.json(
        {
          error: "Too many requests",
          limit: ipLimit.limit,
          remaining: ipLimit.remaining,
          resetTime: ipLimit.resetTime,
        },
        {
          status: 429,
          headers: {
            "X-RateLimit-Limit": ipLimit.limit.toString(),
            "X-RateLimit-Remaining": ipLimit.remaining.toString(),
            "X-RateLimit-Reset": ipLimit.resetTime.toISOString(),
            "Retry-After": Math.ceil((ipLimit.resetTime.getTime() - Date.now()) / 1000).toString(),
          },
        }
      );
    }

    // Check rate limit by phone
    const phoneLimit = await checkRateLimit(phone, "phone");
    if (!phoneLimit.success) {
      return NextResponse.json(
        {
          error: "Too many requests for this phone number",
          limit: phoneLimit.limit,
          remaining: phoneLimit.remaining,
          resetTime: phoneLimit.resetTime,
        },
        {
          status: 429,
          headers: {
            "X-RateLimit-Limit": phoneLimit.limit.toString(),
            "X-RateLimit-Remaining": phoneLimit.remaining.toString(),
            "X-RateLimit-Reset": phoneLimit.resetTime.toISOString(),
            "Retry-After": Math.ceil(
              (phoneLimit.resetTime.getTime() - Date.now()) / 1000
            ).toString(),
          },
        }
      );
    }

    // Check if patient exists
    const patient = await prisma.patient.findUnique({
      where: { phone },
      select: {
        phone: true,
        name: true,
        email: true,
      },
    });

    if (!patient) {
      return NextResponse.json(
        { error: "Patient not found. Please register first." },
        { status: 404 }
      );
    }

    // Create Google Calendar event
    const eventId = await createEvent({
      summary: body.summary,
      description: body.description,
      start: startDate,
      patientPhone: phone,
      patientName: body.patientName,
      email: patient.email || undefined,
      isCrisis: body.isCrisis || false,
    });

    // Create appointment in database
    const appointment = await prisma.appointment.create({
      data: {
        patientPhone: phone,
        date: startDate,
        status: "confirmed",
        isCrisis: body.isCrisis || false,
      },
    });

    // Rate limit headers for successful response
    const headers = {
      "X-RateLimit-Limit": phoneLimit.limit.toString(),
      "X-RateLimit-Remaining": phoneLimit.remaining.toString(),
      "X-RateLimit-Reset": phoneLimit.resetTime.toISOString(),
    };

    return NextResponse.json(
      {
        success: true,
        appointment: {
          id: appointment.id,
          date: appointment.date.toISOString(),
          status: appointment.status,
          isCrisis: appointment.isCrisis,
          patientPhone: appointment.patientPhone,
        },
        event: {
          id: eventId,
          summary: body.summary,
          start: startDate.toISOString(),
          link: `https://calendar.google.com/calendar/r/eventedit/${eventId}`,
        },
        message: "Appointment scheduled successfully",
      },
      { status: 201, headers }
    );
  } catch (error) {
    console.error("Create event error:", error);

    // Handle Google Calendar errors
    if (
      error instanceof Error &&
      error.message.includes("The requested time slot is no longer available")
    ) {
      return NextResponse.json(
        {
          error: "This time slot is no longer available. Please select another time.",
          code: "SLOT_UNAVAILABLE",
        },
        { status: 409 }
      );
    }

    return NextResponse.json(
      {
        error: "Internal server error",
        details: error instanceof Error ? error.message : "Unknown error",
      },
      { status: 500 }
    );
  }
}
