"use client";

import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { Plus, Trash2 } from "lucide-react";
import { AdminDialog } from "@/components/ui/admin-dialog";
import { createVendor, updateVendor, toggleVendorActive } from "./actions";

type ContactRow = { name: string; role: string; mobile: string; email: string; isPrimary: boolean };

type VendorRow = {
  id: string; name: string; vendorId: string | null; address: string | null;
  pincode: string | null; gstin: string | null; isActive: boolean;
  contacts: ContactRow[];
};

const INPUT = "w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20";
const INPUT_SM = "w-full rounded border border-neutral-300 px-2 py-1.5 text-xs focus:border-primary-500 focus:outline-none";

type GstResult = {
  legalName: string; tradeName: string; address: string;
  pincode: string; gstin: string; status: string; registrationDate: string;
};

function ContactsEditor({ initial }: { initial?: ContactRow[] }) {
  const blank = (): ContactRow => ({ name: "", role: "", mobile: "", email: "", isPrimary: false });
  const [rows, setRows] = useState<ContactRow[]>(initial?.length ? initial : [blank()]);

  function update(i: number, field: keyof ContactRow, value: string | boolean) {
    setRows(rows.map((r, idx) => idx === i ? { ...r, [field]: value } : r));
  }

  function setPrimary(i: number) {
    setRows(rows.map((r, idx) => ({ ...r, isPrimary: idx === i })));
  }

  function remove(i: number) {
    if (rows.length === 1) { setRows([blank()]); return; }
    setRows(rows.filter((_, idx) => idx !== i));
  }

  return (
    <div>
      <div className="flex items-center justify-between mb-2">
        <label className="block text-xs font-medium text-neutral-700">Contacts</label>
        <button
          type="button"
          onClick={() => setRows([...rows, blank()])}
          className="flex items-center gap-1 text-xs text-primary-600 hover:text-primary-700 font-medium"
        >
          <Plus className="h-3 w-3" /> Add contact
        </button>
      </div>
      <div className="space-y-2">
        {rows.map((row, i) => (
          <div key={i} className="rounded-lg border border-neutral-200 bg-neutral-50 p-2 space-y-1.5">
            <div className="grid grid-cols-2 gap-1.5">
              <input
                name={`contacts[${i}].name`}
                value={row.name}
                onChange={(e) => update(i, "name", e.target.value)}
                placeholder="Name *"
                className={INPUT_SM}
              />
              <input
                name={`contacts[${i}].role`}
                value={row.role}
                onChange={(e) => update(i, "role", e.target.value)}
                placeholder="Role (e.g. Sales)"
                className={INPUT_SM}
              />
            </div>
            <div className="grid grid-cols-2 gap-1.5">
              <input
                name={`contacts[${i}].mobile`}
                value={row.mobile}
                onChange={(e) => update(i, "mobile", e.target.value)}
                placeholder="Mobile"
                className={INPUT_SM}
              />
              <input
                name={`contacts[${i}].email`}
                value={row.email}
                onChange={(e) => update(i, "email", e.target.value)}
                placeholder="Email"
                type="email"
                className={INPUT_SM}
              />
            </div>
            <input type="hidden" name={`contacts[${i}].isPrimary`} value={String(row.isPrimary)} />
            <div className="flex items-center justify-between">
              <label className="flex items-center gap-1.5 text-xs text-neutral-500 cursor-pointer">
                <input
                  type="checkbox"
                  checked={row.isPrimary}
                  onChange={() => setPrimary(i)}
                  className="rounded border-neutral-300"
                />
                Primary contact
              </label>
              <button
                type="button"
                onClick={() => remove(i)}
                className="text-neutral-400 hover:text-danger-600"
              >
                <Trash2 className="h-3.5 w-3.5" />
              </button>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// CAPTCHA popup — overlays the vendor form (which is itself an AdminDialog at z-50) so the
// CAPTCHA never grows the form and pushes its footer buttons off-screen. Sits at z-[60] and
// handles Escape on the capture phase so closing it does NOT also close the underlying form.
function CaptchaPopup({ open, onClose, children }: { open: boolean; onClose: () => void; children: React.ReactNode }) {
  useEffect(() => {
    if (!open) return;
    function onKey(e: KeyboardEvent) {
      if (e.key === "Escape") { e.stopImmediatePropagation(); onClose(); }
    }
    document.addEventListener("keydown", onKey, true);
    return () => document.removeEventListener("keydown", onKey, true);
  }, [open, onClose]);

  if (!open) return null;

  return (
    <div
      className="fixed inset-0 z-[60] flex items-center justify-center bg-black/40 p-4"
      onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}
    >
      <div className="w-full max-w-sm rounded-xl bg-white shadow-xl">
        <div className="flex items-center justify-between border-b border-neutral-200 px-5 py-3">
          <h3 className="text-sm font-semibold text-neutral-900">GSTIN CAPTCHA</h3>
          <button
            type="button"
            onClick={onClose}
            aria-label="Close"
            className="text-neutral-400 hover:text-neutral-600 transition-colors text-lg leading-none"
          >
            ✕
          </button>
        </div>
        <div className="px-5 py-4">{children}</div>
      </div>
    </div>
  );
}

function VendorFormFields({ vendor, suggestedVendorId, simple = false }: { vendor?: VendorRow; suggestedVendorId?: string; simple?: boolean }) {
  const [gstin, setGstin] = useState(vendor?.gstin ?? "");
  const [name, setName] = useState(vendor?.name ?? "");
  const [address, setAddress] = useState(vendor?.address ?? "");
  const [pincode, setPincode] = useState(vendor?.pincode ?? "");

  const [captchaStep, setCaptchaStep] = useState<"idle" | "loading" | "ready" | "verifying">("idle");
  const [captchaB64, setCaptchaB64] = useState("");
  const [captchaAnswer, setCaptchaAnswer] = useState("");
  const [sessionId, setSessionId] = useState("");
  const [gstError, setGstError] = useState("");
  const [gstSuccess, setGstSuccess] = useState("");

  async function fetchCaptcha() {
    if (gstin.length < 15) { setGstError("Enter a valid 15-character GSTIN"); return; }
    setCaptchaStep("loading"); setGstError(""); setGstSuccess(""); setCaptchaAnswer("");
    try {
      const res = await fetch("/api/gst/captcha");
      const data = await res.json();
      if (data.error) { setGstError(data.error); setCaptchaStep("idle"); return; }
      setCaptchaB64(data.captchaBase64);
      setSessionId(data.sessionId);
      setCaptchaStep("ready");
    } catch { setGstError("Failed to load CAPTCHA"); setCaptchaStep("idle"); }
  }

  async function submitSearch() {
    if (!captchaAnswer || captchaAnswer.length !== 6) { setGstError("Enter the 6-digit CAPTCHA"); return; }
    setCaptchaStep("verifying"); setGstError("");
    try {
      const res = await fetch("/api/gst", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ gstin, captcha: captchaAnswer, sessionId }),
      });
      const data: GstResult & { error?: string } = await res.json();
      // Keep the popup open on error so the user sees it in context and can retry / get a new image.
      if (data.error) { setGstError(data.error); setCaptchaStep("ready"); return; }
      setName(data.tradeName || data.legalName);
      setAddress(data.address);
      if (data.pincode) setPincode(data.pincode);
      setGstSuccess(`✓ ${data.legalName} — ${data.status} since ${data.registrationDate}`);
      setCaptchaStep("idle");
    } catch { setGstError("Lookup failed"); setCaptchaStep("ready"); }
  }

  // Close the CAPTCHA popup without touching the vendor form fields.
  function closeCaptcha() {
    setCaptchaStep("idle"); setCaptchaAnswer(""); setGstError("");
  }

  return (
    <div className="space-y-3">
      {/* GSTIN lookup */}
      <div>
        <label className="block text-xs font-medium text-neutral-700 mb-1">
          GSTIN <span className="text-neutral-400 font-normal">(auto-fills name, address & location)</span>
        </label>
        <div className="flex gap-2">
          <input
            name="gstin"
            value={gstin}
            onChange={(e) => { setGstin(e.target.value.toUpperCase()); setCaptchaStep("idle"); setGstError(""); setGstSuccess(""); }}
            className={INPUT + " font-mono tracking-widest"}
            placeholder="e.g. 27AAHCP5787B1Z6"
            maxLength={15}
          />
          <button
            type="button"
            onClick={fetchCaptcha}
            disabled={captchaStep === "loading" || captchaStep === "verifying" || gstin.length < 15}
            className="shrink-0 rounded-lg border border-primary-300 bg-primary-50 px-3 py-2 text-sm font-medium text-primary-700 hover:bg-primary-100 disabled:opacity-50 whitespace-nowrap"
          >
            {captchaStep === "loading" ? "Loading…" : "Look up"}
          </button>
        </div>
        <CaptchaPopup open={captchaStep !== "idle"} onClose={closeCaptcha}>
          {captchaStep === "loading" ? (
            <p className="py-4 text-center text-sm text-neutral-500">Loading CAPTCHA…</p>
          ) : (
            <div className="space-y-3">
              <p className="text-xs text-neutral-600">Enter the code shown in the image:</p>
              {captchaB64 && (
                <img src={`data:image/png;base64,${captchaB64}`} alt="CAPTCHA"
                  className="rounded border border-neutral-200 bg-white" style={{ imageRendering: "pixelated", height: 48 }} />
              )}
              <div className="flex gap-2 items-center">
                <input type="text" inputMode="numeric" maxLength={6} value={captchaAnswer}
                  onChange={(e) => setCaptchaAnswer(e.target.value.replace(/\D/g, ""))}
                  placeholder="6 digits"
                  disabled={captchaStep === "verifying"}
                  className="w-28 rounded-lg border border-neutral-300 px-3 py-1.5 text-sm font-mono tracking-widest focus:border-primary-500 focus:outline-none disabled:opacity-60"
                  autoFocus
                  onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); submitSearch(); } }}
                />
                <button type="button" onClick={submitSearch} disabled={captchaAnswer.length !== 6 || captchaStep === "verifying"}
                  className="rounded-lg bg-primary-600 px-3 py-1.5 text-sm font-semibold text-white hover:bg-primary-700 disabled:opacity-50">
                  {captchaStep === "verifying" ? "Verifying…" : "Verify"}
                </button>
                <button type="button" onClick={fetchCaptcha} disabled={captchaStep === "verifying"}
                  className="text-xs text-neutral-500 hover:underline disabled:opacity-50">
                  New image
                </button>
              </div>
              {gstError && <p className="text-xs text-danger-600">{gstError}</p>}
              <div className="flex justify-end border-t border-neutral-100 pt-3">
                <button type="button" onClick={closeCaptcha}
                  className="rounded-lg border border-neutral-300 px-3 py-1.5 text-sm font-medium text-neutral-700 hover:bg-neutral-50">
                  Cancel
                </button>
              </div>
            </div>
          )}
        </CaptchaPopup>
        {/* Errors before the popup opens (e.g. invalid GSTIN) show inline; in-popup errors show in context above. */}
        {captchaStep === "idle" && gstError && <p className="mt-1 text-xs text-danger-600">{gstError}</p>}
        {gstSuccess && <p className="mt-1 text-xs text-success-700">{gstSuccess}</p>}
      </div>

      {/* Name + Vendor ID */}
      <div className="grid grid-cols-2 gap-3">
        <div className="col-span-2">
          <label className="block text-xs font-medium text-neutral-700 mb-1">Vendor Name *</label>
          <input name="name" value={name} onChange={(e) => setName(e.target.value)} required className={INPUT} />
        </div>
        {!simple && (
          <div>
            <label className="block text-xs font-medium text-neutral-700 mb-1">Vendor ID <span className="text-neutral-400 font-normal">(leave blank if unverified)</span></label>
            <input name="vendorId" defaultValue={vendor?.vendorId ?? suggestedVendorId ?? ""} className={INPUT} placeholder="VND-001" />
          </div>
        )}
      </div>
      {simple && (
        <p className="rounded-lg bg-warning-50 border border-warning-200 px-3 py-2 text-xs text-warning-800">
          This vendor will be created as <strong>unverified</strong>. It becomes verified once a PO is closed with it, or after a Manager/Accounts review.
        </p>
      )}

      {/* Address + Pincode */}
      <div>
        <label className="block text-xs font-medium text-neutral-700 mb-1">Registered Address</label>
        <textarea name="address" value={address} onChange={(e) => setAddress(e.target.value)} rows={2} className={INPUT} />
      </div>
      <div>
        <label className="block text-xs font-medium text-neutral-700 mb-1">
          Pincode <span className="text-neutral-400 font-normal">(used for distance calculation)</span>
        </label>
        <input name="pincode" value={pincode}
          onChange={(e) => setPincode(e.target.value.replace(/\D/g, "").slice(0, 6))}
          className={INPUT + " font-mono"} placeholder="400001" maxLength={6} />
      </div>

      {/* Contacts */}
      <ContactsEditor initial={vendor?.contacts} />
    </div>
  );
}

export function AddVendorButton({ suggestedId, simple = false }: { suggestedId?: string; simple?: boolean }) {
  const router = useRouter();
  const [open, setOpen] = useState(false);
  const [pending, setPending] = useState(false);
  const [error, setError] = useState("");

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault(); setPending(true); setError("");
    const result = await createVendor(new FormData(e.currentTarget));
    if ("error" in result) { setError(result.error); setPending(false); }
    else { setPending(false); setOpen(false); router.refresh(); }
  }

  return (
    <>
      <button onClick={() => setOpen(true)}
        className="rounded-lg bg-primary-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-primary-700">
        + Add Vendor
      </button>
      <AdminDialog title="Add Vendor" open={open} onClose={() => setOpen(false)}>
        <form onSubmit={handleSubmit} className="space-y-4">
          <VendorFormFields suggestedVendorId={suggestedId} simple={simple} />
          {error && <p className="text-sm text-danger-700 bg-danger-50 rounded-lg px-3 py-2">{error}</p>}
          <div className="flex justify-end gap-3">
            <button type="button" onClick={() => setOpen(false)}
              className="rounded-lg border border-neutral-300 px-4 py-2 text-sm font-medium text-neutral-700">Cancel</button>
            <button type="submit" disabled={pending}
              className="rounded-lg bg-primary-600 px-4 py-2 text-sm font-semibold text-white disabled:opacity-60">
              {pending ? "Creating…" : "Create Vendor"}
            </button>
          </div>
        </form>
      </AdminDialog>
    </>
  );
}

export function EditVendorButton({
  vendor,
  open: controlledOpen,
  onOpenChange,
}: {
  vendor: VendorRow;
  open?: boolean;
  onOpenChange?: (v: boolean) => void;
}) {
  const router = useRouter();
  const [internalOpen, setInternalOpen] = useState(false);
  const [pending, setPending] = useState(false);
  const [error, setError] = useState("");

  const isControlled = controlledOpen !== undefined;
  const open = isControlled ? controlledOpen : internalOpen;
  const setOpen = isControlled ? (onOpenChange ?? (() => {})) : setInternalOpen;

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault(); setPending(true); setError("");
    const fd = new FormData(e.currentTarget);
    fd.set("id", vendor.id);
    const result = await updateVendor(fd);
    if ("error" in result) { setError(result.error); setPending(false); }
    else { setPending(false); setOpen(false); router.refresh(); }
  }

  return (
    <>
      {!isControlled && (
        <button onClick={() => setOpen(true)} className="rounded border border-primary-200 bg-primary-50 px-2.5 py-1 text-xs font-medium text-primary-700 hover:bg-primary-100 transition-colors">Edit</button>
      )}
      <AdminDialog title={`Edit — ${vendor.name}`} open={open} onClose={() => setOpen(false)}>
        <form onSubmit={handleSubmit} className="space-y-4">
          <VendorFormFields vendor={vendor} />
          {error && <p className="text-sm text-danger-700 bg-danger-50 rounded-lg px-3 py-2">{error}</p>}
          <div className="flex justify-end gap-3">
            <button type="button" onClick={() => setOpen(false)}
              className="rounded-lg border border-neutral-300 px-4 py-2 text-sm font-medium text-neutral-700">Cancel</button>
            <button type="submit" disabled={pending}
              className="rounded-lg bg-primary-600 px-4 py-2 text-sm font-semibold text-white disabled:opacity-60">
              {pending ? "Saving…" : "Save"}
            </button>
          </div>
        </form>
      </AdminDialog>
    </>
  );
}
