"use client";

import { useState } from "react";
import { useRouter } from "next/navigation";
import type { ApplicationStage, InterviewOutcome, SalaryRateBasis } from "@prisma/client";
import { AdminDialog } from "@/components/ui/admin-dialog";
import {
  advanceStage,
  agreeSalary,
  approveSalary,
  returnSalary,
  verifyDocuments,
  recordReferenceCheck,
  recordInterviewResult,
  requestInterviewWaiver,
  approveInterviewWaiver,
  selectCandidate,
  returnSelection,
  rejectApplication,
  onboardCandidate,
} from "./actions";

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 PRIMARY = "rounded-lg bg-primary-600 px-4 py-2 text-sm font-semibold text-white hover:bg-primary-700 disabled:opacity-60";
const SECONDARY = "rounded-lg border border-neutral-300 px-4 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-50 disabled:opacity-60";
const DANGER = "rounded-lg border border-danger-300 px-4 py-2 text-sm font-medium text-danger-700 hover:bg-danger-50 disabled:opacity-60";

export type ActionCardProps = {
  id: string;
  stage: ApplicationStage;
  isExHand: boolean;
  interviewResult: InterviewOutcome;
  interviewWaived: boolean;
  rejectedReason: string | null;
  salaryPending: boolean;
  waiverPending: boolean;
  selectionPending: boolean;
  employeeNo: string | null;
  salary: { rateBasis: SalaryRateBasis; basic: number; victualingPerDay: number; currency: string; approved: boolean } | null;
  perms: {
    manage: boolean;
    recordReference: boolean;
    recordInterview: boolean;
    requestWaiver: boolean;
    approveSalary: boolean;
    approveWaiver: boolean;
    select: boolean;
    onboard: boolean;
  };
};

function useAction() {
  const router = useRouter();
  const [pending, setPending] = useState(false);
  const [error, setError] = useState("");
  async function run(fn: () => Promise<{ ok: true } | { error: string }>) {
    setPending(true);
    setError("");
    const res = await fn();
    setPending(false);
    if ("error" in res) setError(res.error);
    else router.refresh();
    return res;
  }
  return { pending, error, run };
}

function Card({ title, sub, children }: { title: string; sub?: string; children: React.ReactNode }) {
  return (
    <div className="rounded-lg border border-neutral-200 bg-white overflow-hidden">
      <div className="px-4 py-3 border-b border-neutral-200 bg-neutral-50">
        <h2 className="text-sm font-semibold text-neutral-900">{title}</h2>
        {sub && <p className="text-xs text-neutral-500 mt-0.5">{sub}</p>}
      </div>
      <div className="p-4 space-y-3">{children}</div>
    </div>
  );
}

function RejectButton({ id }: { id: string }) {
  const router = useRouter();
  const [open, setOpen] = useState(false);
  const [reason, setReason] = useState("");
  const [pending, setPending] = useState(false);
  const [error, setError] = useState("");
  async function submit(e: React.FormEvent) {
    e.preventDefault();
    setPending(true); setError("");
    const res = await rejectApplication(id, reason);
    setPending(false);
    if ("error" in res) setError(res.error); else { setOpen(false); router.refresh(); }
  }
  return (
    <>
      <button className={DANGER} onClick={() => setOpen(true)}>Reject</button>
      <AdminDialog title="Reject candidate" open={open} onClose={() => setOpen(false)}>
        <form onSubmit={submit} className="space-y-4">
          <p className="text-sm text-neutral-600">Rejecting removes this candidate from the pipeline. The reason is recorded.</p>
          <textarea className={INPUT} rows={3} value={reason} onChange={(e) => setReason(e.target.value)} required placeholder="Reason" />
          {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" className={SECONDARY} onClick={() => setOpen(false)}>Cancel</button>
            <button type="submit" disabled={pending} className="rounded-lg bg-danger px-4 py-2 text-sm font-semibold text-white hover:opacity-90 disabled:opacity-60">{pending ? "Rejecting…" : "Reject"}</button>
          </div>
        </form>
      </AdminDialog>
    </>
  );
}

function Err({ msg }: { msg: string }) {
  return msg ? <p className="text-sm text-danger-700 bg-danger-50 rounded-lg px-3 py-2">{msg}</p> : null;
}

export function ApplicationActionCard(p: ActionCardProps) {
  const { run, pending, error } = useAction();
  const canReject = p.perms.manage && !["SELECTED", "ONBOARDED", "REJECTED"].includes(p.stage);

  // Reference-check form state (COMPETENCY_AND_REFERENCES).
  const [ref, setRef] = useState({ refereeName: "", refereeContact: "", outcome: "positive", note: "" });
  // Bank/EPF form state (DOC_VERIFICATION).
  const [docs, setDocs] = useState({ accountName: "", accountNumber: "", ifsc: "", bankName: "", uan: "", aadhaarLast4: "", pfNumber: "" });
  // Salary form state (SALARY_AGREEMENT).
  const [sal, setSal] = useState({ rateBasis: "MONTHLY", basic: "", victualingPerDay: "0", currency: "INR" });

  function fdFrom(obj: Record<string, string>, extra?: Record<string, string>) {
    const fd = new FormData();
    Object.entries({ ...obj, ...extra }).forEach(([k, v]) => fd.set(k, v));
    return fd;
  }

  const footer = (
    <>
      <Err msg={error} />
      {canReject && (
        <div className="flex justify-end pt-1">
          <RejectButton id={p.id} />
        </div>
      )}
    </>
  );

  switch (p.stage) {
    case "SHORTLISTED":
      return (
        <Card title="Shortlisted" sub="Begin vetting: competency & references.">
          {p.perms.manage && (
            <button className={PRIMARY} disabled={pending} onClick={() => run(() => advanceStage(p.id, "start_competency"))}>
              Start competency &amp; references
            </button>
          )}
          {footer}
        </Card>
      );

    case "COMPETENCY_AND_REFERENCES":
      return (
        <Card title="Competency & references" sub="Record reference checks, then verify to continue.">
          {p.perms.recordReference && (
            <div className="space-y-2 rounded-md border border-neutral-200 p-3">
              <p className="text-xs font-medium text-neutral-600">Add a reference check</p>
              <input className={INPUT} placeholder="Referee name" value={ref.refereeName} onChange={(e) => setRef({ ...ref, refereeName: e.target.value })} />
              <input className={INPUT} placeholder="Referee contact (optional)" value={ref.refereeContact} onChange={(e) => setRef({ ...ref, refereeContact: e.target.value })} />
              <input className={INPUT} placeholder="Note (optional)" value={ref.note} onChange={(e) => setRef({ ...ref, note: e.target.value })} />
              <button className={SECONDARY} disabled={pending || !ref.refereeName} onClick={() => run(() => recordReferenceCheck(fdFrom(ref, { applicationId: p.id }))).then((r) => { if ("ok" in r) setRef({ refereeName: "", refereeContact: "", outcome: "positive", note: "" }); })}>
                Save reference
              </button>
            </div>
          )}
          {p.perms.manage && (
            <button className={PRIMARY} disabled={pending} onClick={() => run(() => advanceStage(p.id, "verify_competency"))}>
              Verify &amp; continue to documents
            </button>
          )}
          {footer}
        </Card>
      );

    case "DOC_VERIFICATION":
      return (
        <Card title="Documents" sub="MPO collects & verifies documents, bank and EPF.">
          {p.perms.manage ? (
            <>
              <div className="grid grid-cols-2 gap-2">
                <input className={INPUT} placeholder="Account name" value={docs.accountName} onChange={(e) => setDocs({ ...docs, accountName: e.target.value })} />
                <input className={INPUT} placeholder="Account number" value={docs.accountNumber} onChange={(e) => setDocs({ ...docs, accountNumber: e.target.value })} />
                <input className={INPUT} placeholder="IFSC" value={docs.ifsc} onChange={(e) => setDocs({ ...docs, ifsc: e.target.value })} />
                <input className={INPUT} placeholder="Bank name" value={docs.bankName} onChange={(e) => setDocs({ ...docs, bankName: e.target.value })} />
                <input className={INPUT} placeholder="UAN" value={docs.uan} onChange={(e) => setDocs({ ...docs, uan: e.target.value })} />
                <input className={INPUT} placeholder="Aadhaar (last 4)" value={docs.aadhaarLast4} onChange={(e) => setDocs({ ...docs, aadhaarLast4: e.target.value })} />
                <input className={INPUT} placeholder="PF number" value={docs.pfNumber} onChange={(e) => setDocs({ ...docs, pfNumber: e.target.value })} />
              </div>
              <button className={PRIMARY} disabled={pending} onClick={() => run(() => verifyDocuments(fdFrom(docs, { applicationId: p.id })))}>
                Verify &amp; continue to salary
              </button>
            </>
          ) : (
            <p className="text-sm text-neutral-500">Awaiting document verification by the MPO.</p>
          )}
          {footer}
        </Card>
      );

    case "SALARY_AGREEMENT":
      if (p.salaryPending) {
        return (
          <Card title="Salary" sub="Office-only; the Manager approves.">
            <p className="text-sm text-neutral-600">
              Proposed: <strong>{p.salary?.currency} {p.salary?.basic}</strong> / {p.salary?.rateBasis.toLowerCase()} · victualing {p.salary?.currency} {p.salary?.victualingPerDay}/day
            </p>
            {p.perms.approveSalary ? (
              <div className="flex gap-2">
                <button className={PRIMARY} disabled={pending} onClick={() => run(() => approveSalary(p.id))}>Approve salary</button>
                <ReturnButton label="Return salary" onReturn={(reason) => returnSalary(p.id, reason)} />
              </div>
            ) : (
              <p className="text-sm text-warning-700 bg-warning-50 rounded-lg px-3 py-2">Awaiting Manager approval.</p>
            )}
            {footer}
          </Card>
        );
      }
      return (
        <Card title="Salary" sub="Office-only; the Manager approves.">
          {p.perms.manage ? (
            <>
              <div className="grid grid-cols-2 gap-2">
                <select className={INPUT} value={sal.rateBasis} onChange={(e) => setSal({ ...sal, rateBasis: e.target.value })}>
                  <option value="MONTHLY">Per month</option>
                  <option value="DAILY">Per day</option>
                </select>
                <input className={INPUT} type="number" placeholder="Basic" value={sal.basic} onChange={(e) => setSal({ ...sal, basic: e.target.value })} />
                <input className={INPUT} type="number" placeholder="Victualing / day" value={sal.victualingPerDay} onChange={(e) => setSal({ ...sal, victualingPerDay: e.target.value })} />
              </div>
              <button className={PRIMARY} disabled={pending || !sal.basic} onClick={() => run(() => agreeSalary(fdFrom(sal, { applicationId: p.id })))}>
                Agree salary &amp; send for approval
              </button>
            </>
          ) : (
            <p className="text-sm text-neutral-500">Awaiting the MPO to agree the salary.</p>
          )}
          {footer}
        </Card>
      );

    case "PROPOSED":
      return (
        <Card title="Proposed" sub="Awaiting the candidate's acceptance.">
          {p.perms.manage && (
            <button className={PRIMARY} disabled={pending} onClick={() => run(() => advanceStage(p.id, "propose_accepted"))}>
              Candidate accepted — schedule interview
            </button>
          )}
          {footer}
        </Card>
      );

    case "INTERVIEW":
      return (
        <Card title="Interview" sub="MPO records the result; the Manager approves the selection.">
          {/* Interview result row */}
          {p.interviewResult === "PENDING" && !p.interviewWaived && p.perms.recordInterview && (
            <div className="flex gap-2">
              <button className={PRIMARY} disabled={pending} onClick={() => run(() => recordInterviewResult(p.id, true))}>Interview passed</button>
              <button className={DANGER} disabled={pending} onClick={() => run(() => recordInterviewResult(p.id, false))}>Interview failed</button>
            </div>
          )}
          {/* Waiver (ex-hand) */}
          {p.isExHand && !p.interviewWaived && p.interviewResult === "PENDING" && !p.waiverPending && p.perms.requestWaiver && (
            <button className={SECONDARY} disabled={pending} onClick={() => run(() => requestInterviewWaiver(p.id))}>Request interview waiver → Manager</button>
          )}
          {p.waiverPending && (
            p.perms.approveWaiver ? (
              <div className="flex items-center gap-2">
                <span className="text-sm text-warning-700">Waiver requested.</span>
                <button className={PRIMARY} disabled={pending} onClick={() => run(() => approveInterviewWaiver(p.id))}>Approve waiver</button>
              </div>
            ) : (
              <p className="text-sm text-warning-700 bg-warning-50 rounded-lg px-3 py-2">Interview waiver awaiting Manager approval.</p>
            )
          )}
          {/* Selection row */}
          {(p.interviewResult === "ACCEPTED" || p.interviewWaived) && (
            p.perms.select ? (
              <div className="flex gap-2">
                <button className={PRIMARY} disabled={pending} onClick={() => run(() => selectCandidate(p.id))}>Approve — select</button>
                <ReturnButton label="Return" onReturn={(reason) => returnSelection(p.id, reason)} />
              </div>
            ) : (
              <p className="text-sm text-success-700 bg-success-50 rounded-lg px-3 py-2">{p.interviewWaived ? "Interview waived" : "Interview passed"} — awaiting Manager selection.</p>
            )
          )}
          {footer}
        </Card>
      );

    case "SELECTED":
      return (
        <Card title="Selected" sub="Ready to onboard.">
          <p className="text-sm text-success-700 bg-success-50 rounded-lg px-3 py-2">Candidate selected.</p>
          {p.perms.onboard && <OnboardButton id={p.id} />}
        </Card>
      );

    case "REJECTED":
      return (
        <Card title="Rejected">
          <p className="text-sm text-danger-700 bg-danger-50 rounded-lg px-3 py-2">{p.rejectedReason ?? "This candidate was rejected."}</p>
        </Card>
      );

    default:
      return (
        <Card title="Onboarded">
          <p className="text-sm text-success-700 bg-success-50 rounded-lg px-3 py-2">
            Onboarded to crew{p.employeeNo ? <> · <span className="font-mono">{p.employeeNo}</span></> : null}.
          </p>
        </Card>
      );
  }
}

function OnboardButton({ id }: { id: string }) {
  const router = useRouter();
  const [open, setOpen] = useState(false);
  const [joiningDate, setJoiningDate] = useState("");
  const [contract, setContract] = useState<File | null>(null);
  const [pending, setPending] = useState(false);
  const [error, setError] = useState("");

  async function submit(e: React.FormEvent) {
    e.preventDefault();
    setPending(true); setError("");
    const fd = new FormData();
    fd.set("applicationId", id);
    fd.set("joiningDate", joiningDate);
    if (contract) fd.set("contract", contract);
    const res = await onboardCandidate(fd);
    setPending(false);
    if ("error" in res) setError(res.error); else { setOpen(false); router.refresh(); }
  }

  return (
    <>
      <button className={PRIMARY} onClick={() => setOpen(true)}>Onboard to crew</button>
      <AdminDialog title="Onboard to crew" open={open} onClose={() => setOpen(false)}>
        <form onSubmit={submit} className="space-y-4">
          <div>
            <label className="block text-xs font-medium text-neutral-700 mb-1">Joining date *</label>
            <input type="date" className={INPUT} value={joiningDate} onChange={(e) => setJoiningDate(e.target.value)} required />
          </div>
          <div>
            <label className="block text-xs font-medium text-neutral-700 mb-1">Contract letter (optional)</label>
            <input type="file" accept=".pdf,.doc,.docx" className="block w-full text-sm text-neutral-600 file:mr-3 file:rounded-md file:border-0 file:bg-neutral-100 file:px-3 file:py-1.5 file:text-sm file:font-medium" onChange={(e) => setContract(e.target.files?.[0] ?? null)} />
          </div>
          <div className="rounded-md bg-neutral-50 border border-neutral-200 p-3">
            <p className="text-xs font-medium text-neutral-600 mb-1">Starts automatically on confirm</p>
            <p className="text-xs text-neutral-500">Employee number · salary &amp; victualing · attendance · experience · EPF/PF · PPE. (Attendance, experience and PPE records begin in a later phase.)</p>
          </div>
          {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" className={SECONDARY} onClick={() => setOpen(false)}>Cancel</button>
            <button type="submit" disabled={pending || !joiningDate} className={PRIMARY}>{pending ? "Onboarding…" : "Confirm onboarding"}</button>
          </div>
        </form>
      </AdminDialog>
    </>
  );
}

function ReturnButton({ label, onReturn }: { label: string; onReturn: (reason: string) => Promise<{ ok: true } | { error: string }> }) {
  const router = useRouter();
  const [open, setOpen] = useState(false);
  const [reason, setReason] = useState("");
  const [pending, setPending] = useState(false);
  const [error, setError] = useState("");
  async function submit(e: React.FormEvent) {
    e.preventDefault();
    setPending(true); setError("");
    const res = await onReturn(reason);
    setPending(false);
    if ("error" in res) setError(res.error); else { setOpen(false); router.refresh(); }
  }
  return (
    <>
      <button type="button" className={SECONDARY} onClick={() => setOpen(true)}>{label}</button>
      <AdminDialog title={label} open={open} onClose={() => setOpen(false)}>
        <form onSubmit={submit} className="space-y-4">
          <textarea className={INPUT} rows={3} value={reason} onChange={(e) => setReason(e.target.value)} required placeholder="Reason for returning" />
          {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" className={SECONDARY} onClick={() => setOpen(false)}>Cancel</button>
            <button type="submit" disabled={pending} className={PRIMARY}>{pending ? "Returning…" : "Return"}</button>
          </div>
        </form>
      </AdminDialog>
    </>
  );
}
