"use client";

import { useEffect, useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import { ArrowLeft, FileCheck2 } from "lucide-react";
import { customerApi } from "@/lib/api/customer";
import { ApiException } from "@/lib/api/client";
import { useToken } from "@/lib/auth/useToken";
import type { ApiCreditDocumentType, ApiCreditRequest } from "@/lib/api/types";
import Loader from "@/components/ui/Loader";
import FieldError from "@/components/ui/FieldError";
import { formatCurrency } from "@/lib/utils";

const TENURES = [30, 60, 90] as const;
const MAX_FILE_MB = 10;
const ACCEPT = ".pdf,.jpg,.jpeg,.png";

/**
 * Apply for a credit facility (B30): which facility, how much, for how long,
 * and the documents that facility is underwritten on — uploaded as files.
 *
 * The old form showed every facility as "—" (it read a `title` the admin never
 * fills), rendered file fields as text boxes and never sent a document.
 */
export default function CreditRequestForm({ existing }: { existing?: ApiCreditRequest }) {
  const router = useRouter();
  const { token, ready } = useToken();
  const isEdit = !!existing;

  const [docTypes, setDocTypes] = useState<ApiCreditDocumentType[]>([]);
  const [docTypeId, setDocTypeId] = useState<number | "">(existing?.credit_wallet_document_type_id ?? "");
  const [amount, setAmount] = useState(existing?.amount ? String(existing.amount) : "");
  const [tenure, setTenure] = useState<number>(existing?.tenure_days ?? 30);
  const [texts, setTexts] = useState<Record<number, string>>(() => {
    const out: Record<number, string> = {};
    (existing?.submitted ?? []).forEach((f, i) => {
      if (f.type !== "file" && f.value) out[i] = String(f.value);
    });
    return out;
  });
  const [files, setFiles] = useState<Record<number, File | null>>({});
  const [notes, setNotes] = useState(existing?.notes ?? "");
  const [loading, setLoading] = useState(true);
  const [submitting, setSubmitting] = useState(false);
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [err, setErr] = useState<string | null>(null);

  useEffect(() => {
    if (!ready || !token) return;
    setLoading(true);
    customerApi
      .creditDocumentTypes(token)
      .then((r) => setDocTypes(r.data))
      .catch((e: Error) => setErr(e.message))
      .finally(() => setLoading(false));
  }, [ready, token]);

  const selected = useMemo(() => docTypes.find((d) => d.id === docTypeId), [docTypes, docTypeId]);
  const fields = selected?.fields ?? [];
  const alreadyUploaded = (i: number) => Boolean(existing?.submitted?.[i]?.url);

  function validate(): Record<string, string> {
    const out: Record<string, string> = {};
    if (!docTypeId) out.credit_wallet_document_type_id = "Choose a credit facility";
    const amt = Number(amount);
    if (!amount || !Number.isFinite(amt) || amt < 100000) out.amount = "Minimum credit limit you can request is ₹1,00,000";
    fields.forEach((f) => {
      if (f.type === "file") {
        const file = files[f.index];
        if (file && !/\.(pdf|jpe?g|png)$/i.test(file.name)) out[`files.${f.index}`] = `${f.label}: upload a PDF, JPG or PNG`;
        else if (file && file.size > MAX_FILE_MB * 1024 * 1024) out[`files.${f.index}`] = `${f.label}: file must be under ${MAX_FILE_MB} MB`;
        else if (f.required && !file && !alreadyUploaded(f.index)) out[`files.${f.index}`] = `${f.label} is required`;
      } else if (f.required && !texts[f.index]?.trim()) {
        out[`fields.${f.index}`] = `${f.label} is required`;
      }
    });
    return out;
  }

  async function onSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!token) return;
    setErr(null);
    const v = validate();
    setErrors(v);
    if (Object.keys(v).length > 0) return;

    const fd = new FormData();
    fd.append("credit_wallet_document_type_id", String(docTypeId));
    fd.append("amount", amount);
    fd.append("tenure_days", String(tenure));
    if (notes.trim()) fd.append("notes", notes.trim());
    fields.forEach((f) => {
      if (f.type === "file") {
        const file = files[f.index];
        if (file) fd.append(`files[${f.index}]`, file);
      } else {
        fd.append(`fields[${f.index}]`, texts[f.index] ?? "");
      }
    });

    setSubmitting(true);
    try {
      if (isEdit && existing) {
        // Multipart has to go as POST: PHP does not parse files on a real PUT.
        fd.append("_method", "PUT");
        await customerApi.updateCreditRequestMultipart(token, existing.id, fd);
        router.push(`/credit-request/${existing.id}`);
      } else {
        const r = await customerApi.createCreditRequestMultipart(token, fd);
        router.push(`/credit-request/${r.data.id}`);
      }
    } catch (e) {
      if (e instanceof ApiException && e.errors) {
        const mapped: Record<string, string> = {};
        for (const [k, m] of Object.entries(e.errors)) if (m?.[0]) mapped[k] = m[0];
        setErrors(mapped);
        if (Object.keys(mapped).length === 0) setErr(e.message);
      } else {
        setErr(e instanceof Error ? e.message : "Could not submit");
      }
      setSubmitting(false);
    }
  }

  if (!ready || loading) {
    return (
      <div className="rounded-xl bg-white p-10 shadow-sm ring-1 ring-gray-100">
        <Loader label="Loading…" />
      </div>
    );
  }

  const inputCls = "w-full rounded-lg border border-gray-200 px-3 py-2 text-sm focus:border-[#CC1414] focus:outline-none";

  return (
    <div className="space-y-4">
      <Link href="/credit-request" className="inline-flex items-center gap-1 text-sm text-gray-600 hover:text-[#CC1414]">
        <ArrowLeft className="h-4 w-4" /> Back to credit requests
      </Link>
      <h1 className="text-2xl font-bold text-gray-900">{isEdit ? "Update credit request" : "Apply for credit"}</h1>

      <form onSubmit={onSubmit} noValidate className="space-y-5 rounded-xl bg-white p-6 shadow-sm ring-1 ring-gray-100">
        <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
          <div className="sm:col-span-3">
            <label htmlFor="cr-type" className="mb-1 block text-sm font-medium text-gray-700">Credit facility <span className="text-[#CC1414]">*</span></label>
            <select
              id="cr-type"
              value={docTypeId}
              disabled={isEdit}
              onChange={(e) => {
                setDocTypeId(e.target.value ? Number(e.target.value) : "");
                setFiles({});
                setTexts({});
              }}
              className={`${inputCls} bg-white`}
            >
              <option value="">Select a facility</option>
              {docTypes.map((d) => (
                <option key={d.id} value={d.id}>
                  {d.name}
                </option>
              ))}
            </select>
            <FieldError message={errors.credit_wallet_document_type_id} />
          </div>

          <div className="sm:col-span-2">
            <label htmlFor="cr-amount" className="mb-1 block text-sm font-medium text-gray-700">Credit limit required (₹) <span className="text-[#CC1414]">*</span></label>
            <input
              id="cr-amount"
              inputMode="numeric"
              value={amount}
              onChange={(e) => setAmount(e.target.value.replace(/\D/g, ""))}
              placeholder="e.g. 2500000"
              className={inputCls}
            />
            {Number(amount) > 0 && !errors.amount && <p className="mt-1 text-xs text-gray-500">{formatCurrency(Number(amount))}</p>}
            <FieldError message={errors.amount} />
          </div>

          <div>
            <label htmlFor="cr-tenure" className="mb-1 block text-sm font-medium text-gray-700">Credit period <span className="text-[#CC1414]">*</span></label>
            <select id="cr-tenure" value={tenure} onChange={(e) => setTenure(Number(e.target.value))} className={`${inputCls} bg-white`}>
              {TENURES.map((t) => (
                <option key={t} value={t}>
                  {t} days
                </option>
              ))}
            </select>
            <FieldError message={errors.tenure_days} />
          </div>
        </div>

        {fields.length > 0 && (
          <div className="space-y-4 border-t border-gray-100 pt-4">
            <h2 className="text-sm font-semibold text-gray-900">Documents required for {selected?.name}</h2>
            {fields.map((f) => {
              const key = f.type === "file" ? `files.${f.index}` : `fields.${f.index}`;
              return (
                <div key={f.index}>
                  <label htmlFor={`cr-f-${f.index}`} className="mb-1 block text-sm font-medium text-gray-700">
                    {f.label} {f.required && <span className="text-[#CC1414]">*</span>}
                  </label>
                  {f.type === "file" ? (
                    <>
                      <input
                        id={`cr-f-${f.index}`}
                        type="file"
                        accept={ACCEPT}
                        onChange={(e) => setFiles((p) => ({ ...p, [f.index]: e.target.files?.[0] ?? null }))}
                        className="block w-full text-sm text-gray-700 file:mr-3 file:rounded-lg file:border-0 file:bg-gray-100 file:px-3 file:py-2 file:text-sm file:font-medium hover:file:bg-gray-200"
                      />
                      {alreadyUploaded(f.index) && !files[f.index] && (
                        <p className="mt-1 inline-flex items-center gap-1 text-xs text-emerald-700">
                          <FileCheck2 size={12} aria-hidden /> Uploaded — choose a file only to replace it
                        </p>
                      )}
                    </>
                  ) : (
                    <input
                      id={`cr-f-${f.index}`}
                      type={f.type === "number" ? "number" : "text"}
                      value={texts[f.index] ?? ""}
                      onChange={(e) => setTexts((p) => ({ ...p, [f.index]: e.target.value }))}
                      className={inputCls}
                    />
                  )}
                  {f.description && <p className="mt-1 text-xs text-gray-500">{f.description}</p>}
                  <FieldError message={errors[key]} />
                </div>
              );
            })}
          </div>
        )}

        <div>
          <label htmlFor="cr-notes" className="mb-1 block text-sm font-medium text-gray-700">Notes for the credit team</label>
          <textarea id="cr-notes" rows={3} value={notes} onChange={(e) => setNotes(e.target.value)} className={inputCls} />
        </div>

        {err && <p role="alert" className="rounded-lg bg-red-50 p-3 text-sm text-red-700 ring-1 ring-red-100">{err}</p>}

        <button type="submit" disabled={submitting} className="rounded-lg bg-[#CC1414] px-6 py-2.5 text-sm font-medium text-white hover:bg-[#a30f0f] disabled:opacity-50">
          {submitting ? "Submitting…" : isEdit ? "Save changes" : "Submit request"}
        </button>
      </form>
    </div>
  );
}
