import { NextRequest, NextResponse } from "next/server";
import { logger } from "@/lib/logger";
import { createClient, getSupabaseAdmin } from "@/lib/supabase/server";
import { sendSms, SMS_TEMPLATES, isValidAuMobile } from "@/lib/sms";
import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from "@/lib/constants";
import { checkRateLimit, getClientIP, createRateLimitResponse } from "@/lib/rate-limit";

const GRACE_PERIOD_HOURS = 48;
const NO_SHOW_RATE_LIMIT = 5;
const NO_SHOW_WINDOW_MS = 15 * 60 * 1000;

/**
 * POST /api/match/no-show
 * 
 * Report a worker as no-show. Only the contractor who owns the job can do this.
 * 
 * Rules:
 * - Match must be in "hired" status
 * - Job must have a start_date
 * - At least 48 hours must have passed since start_date (grace period)
 * - Worker gets flagged + notified
 * - Contractor gets SMS confirmation
 * 
 * Body: { matchId: string }
 */
export async function POST(request: NextRequest) {
  try {
    const clientIP = getClientIP(request);
    const rateLimit = await checkRateLimit(`no-show:${clientIP}`, NO_SHOW_RATE_LIMIT, NO_SHOW_WINDOW_MS);
    if (!rateLimit.allowed) {
      const retryAfter = Math.ceil((rateLimit.resetTime - Date.now()) / 1000);
      return createRateLimitResponse(clientIP, retryAfter);
    }

    const supabase = await createClient();
    const { data: { user } } = await supabase.auth.getUser();
    if (!user) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const { matchId } = await request.json();
    if (!matchId) {
      return NextResponse.json({ error: "Missing matchId" }, { status: 400 });
    }

    const admin = getSupabaseAdmin();

    // Fetch match with job and company details
    const { data: match, error: matchError } = await admin
      .from("matches")
      .select(`
        id, status, worker_id, no_show, hired_at,
        jobs!inner(
          id, title, start_date, company_id,
          companies!inner(profile_id, name)
        )
      `)
      .eq("id", matchId)
      .single();

    if (matchError || !match) {
      return NextResponse.json({ error: "Match not found" }, { status: 404 });
    }

    const jobs = match.jobs as unknown as {
      id: string;
      title: string;
      start_date: string | null;
      company_id: string;
      companies: { profile_id: string; name: string };
    };

    // Verify contractor owns this job
    if (jobs.companies.profile_id !== user.id) {
      return NextResponse.json({ error: "Not authorized" }, { status: 403 });
    }

    // Must be hired
    if (match.status !== "hired") {
      return NextResponse.json(
        { error: "Can only report no-show for hired workers" },
        { status: 400 }
      );
    }

    // Already flagged
    if (match.no_show) {
      return NextResponse.json({ error: "Already reported as no-show" }, { status: 409 });
    }

    // Check grace period: 48 hours after start_date (or hired_at if no start_date)
    const referenceDate = jobs.start_date || match.hired_at;
    if (!referenceDate) {
      return NextResponse.json(
        { error: "No start date or hire date to calculate grace period" },
        { status: 400 }
      );
    }

    const refTime = new Date(referenceDate).getTime();
    const gracePeriodMs = GRACE_PERIOD_HOURS * 60 * 60 * 1000;
    const now = Date.now();

    if (now < refTime + gracePeriodMs) {
      const hoursLeft = Math.ceil((refTime + gracePeriodMs - now) / (60 * 60 * 1000));
      return NextResponse.json(
        {
          error: `Grace period not yet expired. ${hoursLeft} hours remaining. You can report a no-show after ${new Date(refTime + gracePeriodMs).toLocaleDateString("en-AU")}.`,
        },
        { status: 400 }
      );
    }

    // Flag the match as no-show
    const { error: updateError } = await admin
      .from("matches")
      .update({
        no_show: true,
        no_show_reported_at: new Date().toISOString(),
        no_show_reported_by: user.id,
      })
      .eq("id", matchId);

    if (updateError) {
      logger.error("Failed to flag no-show:", updateError);
      return NextResponse.json({ error: "Failed to update match" }, { status: HTTP_STATUS_INTERNAL_SERVER_ERROR });
    }

    // Create in-app notification for worker
    await admin.from("notifications").insert({
      profile_id: match.worker_id,
      type: "system",
      title: "No-show reported",
      body: `You were reported as a no-show for "${jobs.title}". This will affect your profile. Contact support if this is incorrect.`,
      data: { matchId, jobTitle: jobs.title, type: "no_show" },
    });

    // Send SMS notifications
    const { data: workerProfile } = await admin
      .from("profiles")
      .select("phone, name")
      .eq("id", match.worker_id)
      .single();

    const { data: contractorProfile } = await admin
      .from("profiles")
      .select("phone")
      .eq("id", user.id)
      .single();

    const smsResults: Array<{ to: string; success: boolean }> = [];

    // SMS to contractor confirming the report
    if (contractorProfile?.phone && isValidAuMobile(contractorProfile.phone)) {
      const result = await sendSms(
        contractorProfile.phone,
        SMS_TEMPLATES.noShowDetected(jobs.title, workerProfile?.name || "The worker")
      );
      smsResults.push({ to: "contractor", success: result.success });
    }

    // Warning SMS to worker
    if (workerProfile?.phone && isValidAuMobile(workerProfile.phone)) {
      const result = await sendSms(
        workerProfile.phone,
        SMS_TEMPLATES.noShowWarning(jobs.title)
      );
      smsResults.push({ to: "worker", success: result.success });
    }

    logger.info(`No-show reported for match ${matchId}`, {
      matchId,
      workerId: match.worker_id,
      jobTitle: jobs.title,
      reportedBy: user.id,
      smsResults,
    });

    return NextResponse.json({
      success: true,
      message: "No-show reported. Worker has been notified.",
    });
  } catch (error) {
    logger.error("No-show report error:", error);
    return NextResponse.json(
      { error: "Failed to report no-show" },
      { status: HTTP_STATUS_INTERNAL_SERVER_ERROR }
    );
  }
}
