import { NextRequest, NextResponse } from "next/server";
import { logger } from "@/lib/logger";
import { createClient } from "@/lib/supabase/server";
import { checkRateLimit, getClientIP, createRateLimitResponse } from "@/lib/rate-limit";
import { withCSRFProtection } from "@/lib/csrf";

const GEOCODE_RATE_LIMIT = 20;
const GEOCODE_WINDOW_MS = 15 * 60 * 1000;

/**
 * Geocoding API endpoint
 * Converts Australian suburb names to latitude/longitude coordinates
 * Uses Nominatim (OpenStreetMap) - free, no API key required
 */
const handler = async (req: NextRequest) => {
  try {
    // Rate limiting
    const clientIP = getClientIP(req);
    const rateLimit = await checkRateLimit(`geocode:${clientIP}`, GEOCODE_RATE_LIMIT, GEOCODE_WINDOW_MS);
    if (!rateLimit.allowed) {
      const retryAfter = Math.ceil((rateLimit.resetTime - Date.now()) / 1000);
      return createRateLimitResponse(clientIP, retryAfter);
    }

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

    const body = await req.json();
    const { suburb } = body;

    if (!suburb || typeof suburb !== "string") {
      return NextResponse.json(
        { error: "Suburb is required" },
        { status: 400 }
      );
    }

    // Add "Australia" to improve geocoding accuracy
    const searchQuery = suburb.includes("Australia")
      ? suburb
      : `${suburb}, Australia`;

    // Use Nominatim (OpenStreetMap) - free geocoding service
    const response = await fetch(
      `https://nominatim.openstreetmap.org/search?` +
        new URLSearchParams({
          q: searchQuery,
          format: "json",
          limit: "1",
          countrycodes: "au", // Restrict to Australia
        }),
      {
        headers: {
          "User-Agent": "RateRight/2.0 (Construction Hiring Platform)",
        },
      }
    );

    if (!response.ok) {
      logger.error("Nominatim API error:", response.statusText);
      return NextResponse.json(
        { error: "Geocoding service unavailable" },
        { status: 503 }
      );
    }

    const data = await response.json();

    if (!data || data.length === 0) {
      return NextResponse.json(
        { error: "Location not found" },
        { status: 404 }
      );
    }

    const location = data[0];
    const lat = parseFloat(location.lat);
    const lng = parseFloat(location.lon);

    if (isNaN(lat) || isNaN(lng)) {
      return NextResponse.json(
        { error: "Invalid coordinates returned" },
        { status: 500 }
      );
    }

    return NextResponse.json({
      suburb,
      location: { lat, lng },
      displayName: location.display_name,
    });
  } catch (error) {
    logger.error("Geocoding error:", error);
    return NextResponse.json(
      { error: "Failed to geocode location" },
      { status: 500 }
    );
  }
}

// Apply CSRF protection to the handler
export const POST = withCSRFProtection(handler);
