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

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

function json(body: unknown, status = 200) {
  return new Response(JSON.stringify(body), {
    status,
    headers: { ...corsHeaders, "Content-Type": "application/json" },
  });
}

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

  try {
    const { code, email, password, full_name } = await req.json();
    if (!code || !email || !password) {
      return json({ error: "Missing required fields" }, 400);
    }
    if (String(password).length < 8) {
      return json({ error: "Password must be at least 8 characters" }, 400);
    }

    const admin = createClient(
      Deno.env.get("SUPABASE_URL")!,
      Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!,
      { auth: { autoRefreshToken: false, persistSession: false } }
    );

    // Validate code
    const { data: codeRow, error: codeErr } = await admin
      .from("signup_codes")
      .select("*")
      .eq("code", String(code).trim())
      .maybeSingle();

    if (codeErr || !codeRow) return json({ error: "Invalid sign-up code" }, 404);
    if (codeRow.redeemed_at) return json({ error: "This code has already been used" }, 410);
    if (codeRow.expires_at && new Date(codeRow.expires_at) < new Date()) {
      return json({ error: "This code has expired" }, 410);
    }

    const normalizedEmail = String(email).trim().toLowerCase();

    // Create the auth user, auto-confirmed. If the email already exists,
    // update the existing user's password and reuse their account so the
    // signup code can still link them to the owner/rental records.
    let userId: string | null = null;
    const { data: created, error: createErr } = await admin.auth.admin.createUser({
      email: normalizedEmail,
      password: String(password),
      email_confirm: true,
      user_metadata: { full_name: full_name || null },
    });

    if (created?.user) {
      userId = created.user.id;
    } else {
      const msg = (createErr?.message || "").toLowerCase();
      const code = (createErr as any)?.code || (createErr as any)?.error_code;
      const isDuplicate =
        code === "email_exists" ||
        msg.includes("already been registered") ||
        msg.includes("already registered") ||
        msg.includes("already exists");

      if (!isDuplicate) {
        return json({ error: createErr?.message || "Failed to create account" }, 400);
      }

      // Find the existing user by email and reset their password so they can sign in
      let existingId: string | null = null;
      let page = 1;
      while (page <= 20 && !existingId) {
        const { data: list, error: listErr } = await admin.auth.admin.listUsers({ page, perPage: 200 });
        if (listErr) break;
        const match = list?.users?.find((u) => (u.email || "").toLowerCase() === normalizedEmail);
        if (match) existingId = match.id;
        if (!list?.users || list.users.length < 200) break;
        page++;
      }

      if (!existingId) {
        return json({ error: "An account with this email already exists. Please sign in instead." }, 409);
      }

      const { error: updErr } = await admin.auth.admin.updateUserById(existingId, {
        password: String(password),
        email_confirm: true,
        user_metadata: { full_name: full_name || null },
      });
      if (updErr) return json({ error: updErr.message }, 400);
      userId = existingId;
    }

    if (!userId) {
      return json({ error: "Failed to resolve user account" }, 500);
    }

    // Replace default 'homeowner' role from handle_new_user trigger if a different role was assigned
    if (codeRow.role && codeRow.role !== "homeowner") {
      await admin.from("user_roles").delete().eq("user_id", userId).eq("role", "homeowner");
      await admin.from("user_roles").insert({ user_id: userId, role: codeRow.role });
    }

    // Optional owner pin: link the new auth user to the owner record
    if (codeRow.owner_id) {
      await admin
        .from("owners")
        .update({ user_id: userId })
        .eq("id", codeRow.owner_id);
    }

    // Link RV/Boat lot rentals so the renter/owner portal can find them.
    // Strategy:
    //   1. If the code pinned a specific rental_id, link that one.
    //   2. Otherwise, backfill any active rentals that match the pinned owner_id
    //      or whose renter_email matches the new account.
    const isRvRole = codeRow.role === "rv_boat_lot" || codeRow.role === "rv_renter" || codeRow.role === "rv_owner";
    if (isRvRole) {
      const rentalUpdate: Record<string, unknown> = { user_id: userId };
      if (codeRow.role === "rv_owner") rentalUpdate.is_owner = true;

      if (codeRow.rental_id) {
        await admin
          .from("rv_boat_lot_rentals")
          .update(rentalUpdate)
          .eq("id", codeRow.rental_id);
      } else {
        // Match by owner_id (if pinned) OR renter_email
        const orParts: string[] = [];
        if (codeRow.owner_id) orParts.push(`owner_id.eq.${codeRow.owner_id}`);
        orParts.push(`renter_email.eq.${normalizedEmail}`);
        await admin
          .from("rv_boat_lot_rentals")
          .update(rentalUpdate)
          .eq("status", "active")
          .or(orParts.join(","));
      }
    }

    // Mark code redeemed
    await admin
      .from("signup_codes")
      .update({
        redeemed_at: new Date().toISOString(),
        redeemed_by_user_id: userId,
        redeemed_email: normalizedEmail,
      })
      .eq("id", codeRow.id);

    return json({ success: true, role: codeRow.role });
  } catch (e) {
    return json({ error: (e as Error).message || "Unexpected error" }, 500);
  }
});
