import { createClient } from "https://esm.sh/@supabase/supabase-js@2";

const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Headers":
    "authorization, x-client-info, apikey, content-type, x-supabase-client-platform, x-supabase-client-platform-version, x-supabase-client-runtime, x-supabase-client-runtime-version",
};

const RATE_LIMIT_MS = 5_000;
const IP_RATE_LIMIT_MS = 60_000;
const IP_MAX_REQUESTS = 15;
const rateLimitMap = new Map<string, number>();
const ipRequestLog = new Map<string, number[]>();

Deno.serve(async (req) => {
  if (req.method === "OPTIONS") {
    return new Response(null, { headers: corsHeaders });
  }

  try {
    const body = await req.json();
    const { search_term, selected_address_id, selected_address_formatted, fiber_available, max_speed, contact_email, contact_phone } = body;

    // Validate required field
    if (!search_term || typeof search_term !== "string") {
      return new Response(
        JSON.stringify({ error: "Missing or invalid search_term" }),
        { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
      );
    }

    // Length validation
    if (search_term.length > 500) {
      return new Response(
        JSON.stringify({ error: "search_term too long" }),
        { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
      );
    }
    if (selected_address_id && (typeof selected_address_id !== "string" || selected_address_id.length > 100)) {
      return new Response(
        JSON.stringify({ error: "Invalid selected_address_id" }),
        { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
      );
    }
    if (selected_address_formatted && (typeof selected_address_formatted !== "string" || selected_address_formatted.length > 500)) {
      return new Response(
        JSON.stringify({ error: "Invalid selected_address_formatted" }),
        { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
      );
    }

    // Validate contact fields if provided
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    const phoneRegex = /^\+?[1-9]\d{1,14}$/;

    if (contact_email) {
      if (typeof contact_email !== "string" || contact_email.length > 254 || !emailRegex.test(contact_email)) {
        return new Response(
          JSON.stringify({ error: "Invalid contact_email" }),
          { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
        );
      }
    }
    if (contact_phone) {
      if (typeof contact_phone !== "string" || contact_phone.length > 20 || !phoneRegex.test(contact_phone)) {
        return new Response(
          JSON.stringify({ error: "Invalid contact_phone" }),
          { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
        );
      }
    }

    // Rate limiting
    const clientIp = req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() || "unknown";
    const now = Date.now();

    // Global per-IP limit
    const ipLog = ipRequestLog.get(clientIp) || [];
    const recentIpRequests = ipLog.filter((ts) => now - ts < IP_RATE_LIMIT_MS);
    if (recentIpRequests.length >= IP_MAX_REQUESTS) {
      return new Response(
        JSON.stringify({ error: "Too many requests" }),
        { status: 429, headers: { ...corsHeaders, "Content-Type": "application/json" } }
      );
    }

    // Per-IP+term cooldown
    const rateLimitKey = `${clientIp}:${search_term.substring(0, 50)}`;
    const lastRequest = rateLimitMap.get(rateLimitKey);
    if (lastRequest && now - lastRequest < RATE_LIMIT_MS) {
      return new Response(
        JSON.stringify({ error: "Too many requests" }),
        { status: 429, headers: { ...corsHeaders, "Content-Type": "application/json" } }
      );
    }
    rateLimitMap.set(rateLimitKey, now);
    recentIpRequests.push(now);
    ipRequestLog.set(clientIp, recentIpRequests);

    // Cleanup
    if (rateLimitMap.size > 1000) {
      for (const [key, ts] of rateLimitMap) {
        if (now - ts > RATE_LIMIT_MS) rateLimitMap.delete(key);
      }
    }
    if (ipRequestLog.size > 500) {
      for (const [key, timestamps] of ipRequestLog) {
        const valid = timestamps.filter((ts) => now - ts < IP_RATE_LIMIT_MS);
        if (valid.length === 0) ipRequestLog.delete(key);
        else ipRequestLog.set(key, valid);
      }
    }

    // Insert using service role
    const supabase = createClient(
      Deno.env.get("SUPABASE_URL")!,
      Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!
    );

    const { error } = await supabase.from("search_logs").insert({
      search_term,
      selected_address_id: selected_address_id || null,
      selected_address_formatted: selected_address_formatted || null,
      fiber_available: typeof fiber_available === "boolean" ? fiber_available : null,
      max_speed: typeof max_speed === "number" ? max_speed : null,
      contact_email: contact_email || null,
      contact_phone: contact_phone || null,
    });

    if (error) {
      console.error("Insert error:", error.message);
      return new Response(
        JSON.stringify({ error: "Failed to log search" }),
        { status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
      );
    }

    return new Response(
      JSON.stringify({ success: true }),
      { headers: { ...corsHeaders, "Content-Type": "application/json" } }
    );
  } catch (err) {
    console.error("log-search error:", err);
    return new Response(
      JSON.stringify({ error: "Internal server error" }),
      { status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
    );
  }
});
