import { NextRequest, NextResponse } from "next/server";
import OpenAI from "openai";
import { createClient } from "@/lib/supabase/server";
import { checkRateLimit, getClientIP, createRateLimitResponse } from "@/lib/rate-limit";
import { withErrorHandler, APIError, ErrorCodes } from "@/lib/api-errors";
import { sanitizeInput } from "@/lib/sanitize";
import { validateCSRFToken, isSameOrigin } from "@/lib/csrf";

// Cast helper to use NextRequest methods while satisfying withErrorHandler signature
type Handler = (request: Request) => Promise<Response>;

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY || "",
});

const AI_RATE_LIMIT = 10;
const AI_WINDOW_MS = 15 * 60 * 1000;

const VALID_TRADES = [
  "Labourer", "Steel Fixer", "Formworker", "Carpenter", "Electrician",
  "Plumber", "Concreter", "Bricklayer", "Painter", "Roofer",
  "Scaffolder", "Tiler", "Plasterer", "Welder", "Crane Operator",
  "Excavator Operator",
];

const VALID_AVAILABILITY = ["full-time", "casual", "weekends", "flexible"];

async function handler(request: Request) {
  const nextRequest = request as NextRequest;
  // CSRF protection: validate same-origin and token
  if (!isSameOrigin(request)) {
    return NextResponse.json({ error: 'Cross-origin request not allowed' }, { status: 403 });
  }
  const csrfValid = await validateCSRFToken(request);
  if (!csrfValid) {
    return NextResponse.json({ error: 'Invalid or missing CSRF token' }, { status: 403 });
  }
  
  // Auth check
  const supabase = await createClient();
  const { data: { user } } = await supabase.auth.getUser();
  if (!user) {
    throw new APIError("Unauthorized", 401, ErrorCodes.UNAUTHORIZED);
  }

  // Rate limit
  const clientIP = getClientIP(request);
  const rateLimit = checkRateLimit(`parse-voice:${clientIP}`, AI_RATE_LIMIT, AI_WINDOW_MS);
  if (!rateLimit.allowed) {
    const retryAfter = Math.ceil((rateLimit.resetTime - Date.now()) / 1000);
    return createRateLimitResponse(clientIP, retryAfter);
  }

  const body = await request.json();
  const { transcript } = body;

  if (!transcript || typeof transcript !== "string") {
    throw new APIError("Missing transcript", 400, ErrorCodes.INVALID_INPUT);
  }

  // Sanitize transcript to prevent prompt injection
  const sanitizedTranscript = sanitizeInput(transcript, { maxLength: 5000 });

  try {
    const completion = await openai.chat.completions.create({
      model: "gpt-4o-mini",
      messages: [
        {
          role: "system",
          content: `You are a profile parser for an Australian construction hiring app. Extract structured data from a worker's spoken description.

Valid trades: ${VALID_TRADES.join(", ")}
Valid availability: ${VALID_AVAILABILITY.join(", ")}

Return ONLY valid JSON in this exact format:
{
  "trade": "one of the valid trades or null",
  "experience_years": number or null,
  "location": "suburb/area string or null",
  "availability": "one of the valid availability options or null"
}

Match trades loosely — e.g. "sparky" = "Electrician", "chippie" = "Carpenter", "bricky" = "Bricklayer".
For experience, extract the number of years mentioned.
For location, extract any suburb, city, or area name mentioned.
For availability, match to the closest option.
If a field is not mentioned, set it to null.`,
        },
        {
          role: "user",
          content: sanitizedTranscript,
        },
      ],
      temperature: 0.3,
      response_format: { type: "json_object" },
    });

    const content = completion.choices[0]?.message?.content;
    if (!content) {
      throw new APIError("No response from AI", 500, ErrorCodes.EXTERNAL_SERVICE_ERROR);
    }

    const parsed = JSON.parse(content);

    // Validate trade
    if (parsed.trade && !VALID_TRADES.includes(parsed.trade)) {
      parsed.trade = null;
    }

    // Validate availability
    if (parsed.availability && !VALID_AVAILABILITY.includes(parsed.availability)) {
      parsed.availability = null;
    }

    // Validate experience_years
    if (parsed.experience_years !== null && (typeof parsed.experience_years !== "number" || parsed.experience_years < 0)) {
      parsed.experience_years = null;
    }

    return Response.json(parsed);
  } catch (error) {
    console.error("OpenAI parsing error:", error);
    if (error instanceof APIError) {
      throw error;
    }
    throw new APIError(
      "Failed to parse voice input",
      500,
      ErrorCodes.EXTERNAL_SERVICE_ERROR
    );
  }
}

export const POST = withErrorHandler(handler);
