"use server";

import { redirect } from "next/navigation";
import { revalidatePath } from "next/cache";
import { requireOrg, canEditLeads } from "@/lib/ctx";
import { applyStage } from "@/lib/stages";
import { ingestChat } from "@/lib/pipeline";
import { parseChat } from "@/lib/chat-parser";
import { isStage } from "@/lib/stage-defs";

const s = (fd: FormData, k: string) => String(fd.get(k) ?? "").trim();

// Akses dicek lewat RLS (CS hanya bisa membuka lead miliknya), lalu tulis memakai service role.
async function editable(fd: FormData) {
  const c = await requireOrg();
  const id = s(fd, "lead_id");
  if (!canEditLeads(c.role)) redirect(`/leads/${id}`);
  const { data: lead } = await c.db.from("leads").select("id, org_id").eq("id", id).maybeSingle();
  if (!lead || lead.org_id !== c.orgId) redirect("/leads");
  return { c, id };
}

const done = (id: string, e?: string): never => {
  revalidatePath(`/leads/${id}`);
  redirect(`/leads/${id}${e ? `?e=${e}` : ""}`);
};

// Tombol tahap manual (Pilih produk / Kirim data / Minta rekening) dan konfirmasi saran AI
export async function setStage(fd: FormData) {
  const { c, id } = await editable(fd);
  const stage = s(fd, "stage");
  if (!isStage(stage) || stage === "new" || stage === "contacted" || stage === "purchased" || stage === "lost") done(id);
  const at = new Date(s(fd, "at"));
  const confirmed = fd.get("from_ai") === "1";
  await applyStage({
    orgId: c.orgId,
    leadId: id,
    stage: stage as never,
    occurredAt: isNaN(at.getTime()) ? new Date() : at,
    source: confirmed ? "ai_suggested" : "cs",
    userId: c.user.id,
  });
  done(id);
}

export async function markLost(fd: FormData) {
  const { c, id } = await editable(fd);
  await applyStage({ orgId: c.orgId, leadId: id, stage: "lost", occurredAt: new Date(), source: "cs", userId: c.user.id, note: s(fd, "reason") || undefined });
  await c.admin.from("leads").update({ lost_reason: s(fd, "reason") || null }).eq("id", id).eq("org_id", c.orgId);
  done(id);
}

// Closing: catat order, lalu kirim Purchase ke Meta (selalu lewat konfirmasi CS)
export async function closeSale(fd: FormData) {
  const { c, id } = await editable(fd);
  const amount = Number(s(fd, "amount").replace(/[^\d.]/g, ""));
  if (!(amount > 0)) done(id, "amount");

  const qty = Math.max(1, parseInt(s(fd, "quantity") || "1", 10) || 1);
  // input datetime-local tidak punya zona waktu: dianggap WIB
  const paidRaw = s(fd, "paid_at");
  let paidAt = paidRaw ? new Date(`${paidRaw}:00+07:00`) : new Date();
  if (isNaN(paidAt.getTime())) paidAt = new Date();

  const productId = s(fd, "product_id") || null;
  let product: { id: string; name: string; sku: string | null } | null = null;
  if (productId) {
    const { data } = await c.admin.from("products").select("id, name, sku").eq("id", productId).eq("org_id", c.orgId).maybeSingle();
    product = data ?? null;
  }
  const { data: conn } = await c.admin.from("meta_connections").select("currency").eq("org_id", c.orgId).maybeSingle();
  const currency = conn?.currency || "IDR";

  const { data: order, error } = await c.admin
    .from("orders")
    .insert({
      org_id: c.orgId,
      lead_id: id,
      product_id: product?.id ?? null,
      amount,
      currency,
      quantity: qty,
      payment_method: s(fd, "payment_method") || null,
      proof_url: s(fd, "proof_url") || null,
      paid_at: paidAt.toISOString(),
      confirmed_by: c.user.id,
    })
    .select("id")
    .single();
  if (error || !order) done(id, "order");

  await applyStage({
    orgId: c.orgId,
    leadId: id,
    stage: "purchased",
    occurredAt: paidAt,
    source: "cs",
    userId: c.user.id,
    orderId: order!.id,
    customData: {
      value: amount,
      currency,
      content_type: "product",
      num_items: qty,
      order_id: order!.id,
      ...(product ? { content_ids: [product.sku || product.id], content_name: product.name } : {}),
    },
  });
  done(id);
}

// Tambah chat terbaru: skor dihitung ulang dan tahap baru ikut terdeteksi
export async function appendChat(fd: FormData) {
  const { c, id } = await editable(fd);
  const f = fd.get("chat_file");
  const raw = f instanceof File && f.size > 0 ? await f.text() : s(fd, "chat_text");
  const msgs = parseChat(raw);
  if (!msgs.length) done(id, "chat");
  await ingestChat({ orgId: c.orgId, leadId: id, userId: c.user.id, rawText: raw, msgs });
  done(id);
}
