// Avria Sign — public endpoints: lookup envelope by token, submit signature
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.45.0";

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

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

  const url = new URL(req.url);
  const action = url.searchParams.get("action") || "lookup";
  const admin = createClient(Deno.env.get("SUPABASE_URL")!, Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!);

  try {
    if (action === "lookup") {
      const tokenStr = url.searchParams.get("token");
      if (!tokenStr) return json({ error: "missing token" }, 400);

      const { data: recip, error: rErr } = await admin
        .from("signature_recipients")
        .select("id, envelope_id, name, email, status, signed_at")
        .eq("signing_token", tokenStr)
        .maybeSingle();
      if (rErr || !recip) return json({ error: "invalid token" }, 404);

      const { data: env } = await admin
        .from("signature_envelopes")
        .select("id, document_name, document_url, signed_document_url, status, email_body, association_id, voided_at, voided_reason")
        .eq("id", recip.envelope_id)
        .maybeSingle();

      // If voided, return early
      if (env?.status === "voided" || env?.voided_at) {
        return json({ recipient: recip, envelope: env, voided: true });
      }

      // Fetch fields for this recipient
      const { data: fields } = await admin
        .from("signature_fields")
        .select("id, field_type, page_number, x_ratio, y_ratio, width_ratio, height_ratio, required")
        .eq("recipient_id", recip.id)
        .order("page_number");

      // log view event (only first time)
      if (recip.status === "pending") {
        await admin.from("signature_events").insert({
          envelope_id: recip.envelope_id,
          recipient_id: recip.id,
          event_type: "viewed",
          ip_address: req.headers.get("x-forwarded-for") || null,
          user_agent: req.headers.get("user-agent") || null,
        });
        await admin.from("signature_recipients").update({ status: "viewed" }).eq("id", recip.id).eq("status", "pending");
      }

      return json({ recipient: recip, envelope: env, fields: fields || [] });
    }

    if (action === "sign" && req.method === "POST") {
      const body = await req.json();
      const { token, signature_data_url, signature_method } = body;
      if (!token || !signature_data_url) return json({ error: "missing fields" }, 400);

      const { data: recip } = await admin
        .from("signature_recipients")
        .select("id, envelope_id, status")
        .eq("signing_token", token)
        .maybeSingle();
      if (!recip) return json({ error: "invalid token" }, 404);
      if (recip.status === "signed") return json({ error: "already signed" }, 400);

      // Refuse if envelope voided
      const { data: envCheck } = await admin
        .from("signature_envelopes").select("status, voided_at").eq("id", recip.envelope_id).maybeSingle();
      if (envCheck?.status === "voided" || envCheck?.voided_at) {
        return json({ error: "This envelope has been voided and can no longer be signed." }, 400);
      }

      const ip = req.headers.get("x-forwarded-for") || null;
      const ua = req.headers.get("user-agent") || null;

      await admin.from("signature_recipients").update({
        signature_data_url,
        signature_method: signature_method || "draw",
        status: "signed",
        signed_at: new Date().toISOString(),
        signed_ip: ip,
        signed_user_agent: ua,
      }).eq("id", recip.id);

      await admin.from("signature_events").insert({
        envelope_id: recip.envelope_id,
        recipient_id: recip.id,
        event_type: "signed",
        ip_address: ip,
        user_agent: ua,
        details: { method: signature_method || "draw" },
      });

      const { data: allRecips } = await admin
        .from("signature_recipients")
        .select("status")
        .eq("envelope_id", recip.envelope_id);

      const allSigned = (allRecips || []).every(r => r.status === "signed");
      if (allSigned) {
        await admin.from("signature_envelopes").update({
          status: "completed",
          completed_at: new Date().toISOString(),
        }).eq("id", recip.envelope_id);

        await admin.from("signature_events").insert({
          envelope_id: recip.envelope_id,
          event_type: "completed",
        });

        admin.functions.invoke("avria-sign-stamp", {
          body: { envelope_id: recip.envelope_id },
        }).catch(e => console.warn("stamp invoke failed:", e));
      }

      return json({ ok: true, all_signed: allSigned });
    }

    return json({ error: "unknown action" }, 400);
  } catch (err: any) {
    console.error("avria-sign-public error:", err);
    return json({ error: err.message || String(err) }, 500);
  }
});

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