// Avria Sign — stamp signed PDF (using placed fields when available) and append validation certificate
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.45.0";
import { PDFDocument, StandardFonts, rgb } from "https://esm.sh/pdf-lib@1.17.1";

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

function toSmtpSenderConfig(sender: any) {
  const port = Number(sender?.smtp_port ?? 587);
  const isImplicitSslPort = port === 465;
  const isStartTlsPort = port === 587;

  return {
    host: sender.smtp_host,
    port,
    username: sender.smtp_username,
    password: sender.smtp_password,
    use_ssl: isImplicitSslPort ? true : sender.use_ssl ?? false,
    use_tls: isImplicitSslPort ? false : sender.use_tls ?? isStartTlsPort,
    from: sender.sender_name
      ? `${sender.sender_name} <${sender.email_address}>`
      : sender.email_address,
    fromEmail: sender.email_address,
    fromName: sender.sender_name,
    envelopeFrom: sender.smtp_username || sender.email_address,
    signature_html: sender.signature_html || "",
  };
}

Deno.serve(async (req) => {
  if (req.method === "OPTIONS") return new Response(null, { headers: corsHeaders });
  const admin = createClient(Deno.env.get("SUPABASE_URL")!, Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!);

  try {
    const { envelope_id } = await req.json();
    if (!envelope_id) return json({ error: "missing envelope_id" }, 400);

    const { data: env } = await admin
      .from("signature_envelopes").select("*").eq("id", envelope_id).maybeSingle();
    if (!env) return json({ error: "envelope not found" }, 404);

    const { data: recipients } = await admin
      .from("signature_recipients").select("*").eq("envelope_id", envelope_id).order("signing_order");

    const { data: allFields } = await admin
      .from("signature_fields").select("*").eq("envelope_id", envelope_id);

    const pdfRes = await fetch(env.document_url);
    if (!pdfRes.ok) throw new Error("Could not fetch original document");
    const pdfBytes = new Uint8Array(await pdfRes.arrayBuffer());

    let pdfDoc: PDFDocument;
    try {
      pdfDoc = await PDFDocument.load(pdfBytes, { ignoreEncryption: true });
    } catch {
      pdfDoc = await PDFDocument.create();
      const p = pdfDoc.addPage();
      p.drawText("Original document could not be embedded.", { x: 50, y: 700, size: 12 });
    }

    const helv = await pdfDoc.embedFont(StandardFonts.Helvetica);
    const helvBold = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
    const pages = pdfDoc.getPages();

    // Cache embedded signature images per recipient
    const sigImageCache = new Map<string, any>();
    for (const r of recipients || []) {
      if (!r.signature_data_url) continue;
      try {
        const isPng = r.signature_data_url.includes("image/png");
        const base64 = r.signature_data_url.split(",")[1] || "";
        const sigBytes = Uint8Array.from(atob(base64), c => c.charCodeAt(0));
        const img = isPng ? await pdfDoc.embedPng(sigBytes) : await pdfDoc.embedJpg(sigBytes);
        sigImageCache.set(r.id, img);
      } catch (e) { console.warn("sig embed failed:", r.id, e); }
    }

    const fieldsByRecipient = new Map<string, any[]>();
    (allFields || []).forEach(f => {
      const arr = fieldsByRecipient.get(f.recipient_id) || [];
      arr.push(f); fieldsByRecipient.set(f.recipient_id, arr);
    });

    const hasPlacedFields = (allFields || []).length > 0;

    if (hasPlacedFields) {
      // Stamp at each placed field location
      for (const r of recipients || []) {
        const fields = fieldsByRecipient.get(r.id) || [];
        const sigImg = sigImageCache.get(r.id);
        const signedDate = r.signed_at ? new Date(r.signed_at) : new Date();
        const dateStr = signedDate.toLocaleDateString("en-US", { timeZone: "America/New_York" });

        for (const f of fields) {
          const pageIdx = Math.min((f.page_number || 1) - 1, pages.length - 1);
          const page = pages[pageIdx];
          const { width: pw, height: ph } = page.getSize();
          // UI uses top-left origin; pdf-lib uses bottom-left
          const x = f.x_ratio * pw;
          const y = ph - (f.y_ratio + f.height_ratio) * ph;
          const w = f.width_ratio * pw;
          const h = f.height_ratio * ph;

          if (f.field_type === "signature" && sigImg) {
            // Fit signature into box preserving aspect ratio
            const ratio = Math.min(w / sigImg.width, h / sigImg.height);
            const drawW = sigImg.width * ratio;
            const drawH = sigImg.height * ratio;
            page.drawImage(sigImg, {
              x: x + (w - drawW) / 2,
              y: y + (h - drawH) / 2,
              width: drawW, height: drawH,
            });
          } else if (f.field_type === "date") {
            page.drawText(dateStr, { x: x + 4, y: y + h / 2 - 4, size: Math.min(11, h * 0.7), font: helv, color: rgb(0, 0, 0) });
          } else if (f.field_type === "name") {
            page.drawText(r.name, { x: x + 4, y: y + h / 2 - 4, size: Math.min(11, h * 0.7), font: helvBold, color: rgb(0, 0, 0) });
          }
        }
      }
    } else {
      // Fallback: stamp on bottom of last page
      const lastPage = pages[pages.length - 1];
      let stampY = 80;
      for (const r of recipients || []) {
        const sigImg = sigImageCache.get(r.id);
        if (!sigImg) continue;
        const sigDims = sigImg.scale(120 / sigImg.width);
        lastPage.drawImage(sigImg, { x: 50, y: stampY, width: sigDims.width, height: sigDims.height });
        lastPage.drawText(`${r.name}`, { x: 180, y: stampY + 25, size: 9, font: helvBold, color: rgb(0, 0, 0) });
        lastPage.drawText(`Signed: ${new Date(r.signed_at).toLocaleString("en-US", { timeZone: "America/New_York" })} EST`, {
          x: 180, y: stampY + 12, size: 8, font: helv, color: rgb(0.3, 0.3, 0.3),
        });
        lastPage.drawText(`ID: ${r.id.slice(0, 8).toUpperCase()}`, {
          x: 180, y: stampY, size: 7, font: helv, color: rgb(0.5, 0.5, 0.5),
        });
        stampY += 60;
        if (stampY > 250) break;
      }
    }

    // Append Certificate of Validation page
    const cert = pdfDoc.addPage();
    const { width, height } = cert.getSize();

    cert.drawRectangle({ x: 30, y: 30, width: width - 60, height: height - 60, borderColor: rgb(0, 0, 0), borderWidth: 2 });
    cert.drawRectangle({ x: 40, y: 40, width: width - 80, height: height - 80, borderColor: rgb(0, 0, 0), borderWidth: 0.5 });

    cert.drawText("CERTIFICATE OF VALIDATION", { x: width / 2 - 165, y: height - 110, size: 22, font: helvBold });
    cert.drawText("Cryptographic proof of document signing and integrity.", {
      x: width / 2 - 175, y: height - 135, size: 10, font: helv, color: rgb(0.4, 0.4, 0.4),
    });

    let y = height - 200;
    const drawRow = (label: string, value: string) => {
      cert.drawText(label, { x: 70, y, size: 11, font: helvBold });
      cert.drawText(value, { x: 230, y, size: 11, font: helv });
      cert.drawLine({ start: { x: 70, y: y - 5 }, end: { x: width - 70, y: y - 5 }, thickness: 0.3, color: rgb(0.7, 0.7, 0.7) });
      y -= 30;
    };

    drawRow("Document Name:", env.document_name);
    drawRow("Envelope ID:", env.id);
    drawRow("Issued By:", "Avria Community Management");
    drawRow("Completed:", new Date(env.completed_at || Date.now()).toLocaleString("en-US", { timeZone: "America/New_York" }) + " EST");
    drawRow("Status:", "COMPLETED");

    y -= 10;
    cert.drawText("SIGNERS", { x: 70, y, size: 12, font: helvBold });
    y -= 20;

    for (const r of recipients || []) {
      cert.drawText(`• ${r.name} <${r.email}>`, { x: 80, y, size: 10, font: helv });
      y -= 14;
      if (r.signed_at) {
        cert.drawText(
          `   Signed ${new Date(r.signed_at).toLocaleString("en-US", { timeZone: "America/New_York" })} EST` +
          (r.signed_ip ? ` from ${r.signed_ip}` : "") +
          ` (${r.signature_method || "draw"})`,
          { x: 80, y, size: 8, font: helv, color: rgb(0.4, 0.4, 0.4) }
        );
        y -= 12;
      }
      cert.drawText(`   Signature ID: ${r.id}`, { x: 80, y, size: 7, font: helv, color: rgb(0.5, 0.5, 0.5) });
      y -= 16;
    }

    cert.drawCircle({ x: width - 110, y: 110, size: 45, borderColor: rgb(0.2, 0.4, 0.7), borderWidth: 3, opacity: 0.6 });
    cert.drawText("OFFICIAL", { x: width - 130, y: 110, size: 9, font: helvBold, color: rgb(0.2, 0.4, 0.7) });
    cert.drawText("SEAL", { x: width - 122, y: 98, size: 9, font: helvBold, color: rgb(0.2, 0.4, 0.7) });

    const finalBytes = await pdfDoc.save();
    const path = `signature-envelopes/${envelope_id}/signed.pdf`;
    const { error: upErr } = await admin.storage.from("files").upload(path, finalBytes, {
      contentType: "application/pdf", upsert: true,
    });
    if (upErr) throw upErr;
    const { data: pub } = admin.storage.from("files").getPublicUrl(path);

    await admin.from("signature_envelopes").update({ signed_document_url: pub.publicUrl }).eq("id", envelope_id);

    // Notify all signers + creator
    const { data: envFull } = await admin.from("signature_envelopes").select("created_by, document_name").eq("id", envelope_id).single();
    const recipientEmails = (recipients || []).map(r => r.email);
    let creatorEmail: string | null = null;
    if (envFull?.created_by) {
      const { data: creator } = await admin.auth.admin.getUserById(envFull.created_by);
      creatorEmail = creator?.user?.email || null;
    }
    const allEmails = Array.from(new Set([...recipientEmails, ...(creatorEmail ? [creatorEmail] : [])]));

    const { data: defaultSender } = await admin
      .from("email_senders").select("smtp_host, smtp_port, smtp_username, smtp_password, use_tls, use_ssl, email_address, sender_name, signature_html").eq("is_active", true).eq("is_default", true)
      .order("updated_at", { ascending: false }).limit(1).maybeSingle();

    const smtpSender = defaultSender ? toSmtpSenderConfig(defaultSender) : null;

    for (const email of allEmails) {
      try {
        if (smtpSender) {
          const html = `
            <div style="font-family:Arial,sans-serif;max-width:600px;margin:0 auto;padding:20px;">
              <h2 style="color:#059669;">Document Signed</h2>
              <p>The document <strong>${envFull?.document_name || "Document"}</strong> has been signed by all parties.</p>
              <p style="margin:20px 0;">
                <a href="${pub.publicUrl}" style="background:#1e3a8a;color:#fff;padding:12px 24px;text-decoration:none;border-radius:6px;display:inline-block;">Download Signed Copy</a>
              </p>
              <hr style="margin-top:30px;border:none;border-top:1px solid #eee;"/>
              <p style="font-size:11px;color:#999;">Avria Sign — Secure Electronic Signatures</p>
            </div>`;
          await admin.functions.invoke("send-smtp-email", {
            body: {
              sender: smtpSender,
              recipient: email,
              subject: `Signed: ${envFull?.document_name || "Document"}`,
              html,
              body: html,
              fallback_user_id: envFull?.created_by || null,
              feature_type: "signature_completed",
            },
          });
        }
      } catch (e) {
        console.warn("Completion email failed for", email, e);
      }
    }

    return json({ ok: true, signed_document_url: pub.publicUrl });
  } catch (err: any) {
    console.error("avria-sign-stamp 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" },
  });
}
