"use client";

import * as React from "react";
import { MailIcon, MessageSquareIcon } from "lucide-react";

import { Example } from "@/components/design-system/example";
import { Section } from "@/components/design-system/section";
import { ConfirmDialog } from "@/components/medora/confirm-dialog";
import { RecordDrawer } from "@/components/medora/drawer";
import { EmployeeForm, employeeProblems, LeaveBalances, leaveProblems, PayItemsTable, PayslipGroups, unreachable, type EmployeeDraft, type EmployeeTab, type LeaveBalance, type PayItem, type RunEmployee, type RunKind } from "@/components/medora/hr-more";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Field, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";
import { toast } from "@/components/ui/toast";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import { TODAY } from "@/lib/mock-data";

const n2 = (n: number) => n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });

const BLANK: EmployeeDraft = {
  first: "Rose",
  last: "Akinyi",
  idNumber: "28811402",
  dob: "2010-03-14",
  phone: "0712 555 010",
  email: "",
  branch: "Westlands Main",
  department: "Front shop",
  designation: "",
  type: "Permanent",
  start: "2026-11-01",
  payType: "Monthly",
  rate: "32000",
  statutory: { nssf: true, shif: true, levy: true, paye: true },
  user: "",
  payBy: "M-Pesa",
  bank: "",
  account: "",
  mpesa: "",
  kraPin: "A00881140",
  nssfNo: "",
  shaNo: "SHA-11902",
};

function EmployeeDemo() {
  const [open, setOpen] = React.useState(false);
  const [d, setD] = React.useState(BLANK);
  const [tab, setTab] = React.useState<EmployeeTab>("Personal");
  const [tried, setTried] = React.useState(false);
  const problems = employeeProblems(d, TODAY, ["28811401"]);
  return (
    <Example title="Employee" description="Three tabs; Save checks all of them and each tab says how many problems it has. This draft has some on every tab">
      <Button variant="outline" onClick={() => setOpen(true)}>
        Add employee
      </Button>
      <RecordDrawer
        open={open}
        onOpenChange={(o) => !o && setOpen(false)}
        variant="edit"
        width="lg"
        dirty
        onDiscard={() => setD(BLANK)}
        title="New employee"
        footer={
          <>
            <Button variant="outline" onClick={() => setOpen(false)}>
              Cancel
            </Button>
            <Button
              onClick={() => {
                setTried(true);
                const keys = Object.keys(problems) as (keyof EmployeeDraft)[];
                if (!keys.length) {
                  setOpen(false);
                  toast.add({ title: `${d.first} ${d.last} added`, description: "Included from the November payroll." });
                }
              }}
            >
              Save employee
            </Button>
          </>
        }
      >
        <EmployeeForm d={d} onChange={setD} tab={tab} onTab={setTab} problems={tried ? problems : {}} branches={["Westlands Main", "Kilimani", "Nyali", "Milimani"]} types={["Permanent", "Contract", "Casual", "Intern"]} users={["kevin.m", "faith.n", "peter.k"]} />
      </RecordDrawer>
    </Example>
  );
}

const HOLIDAYS = ["2026-10-20", "2026-12-25", "2026-12-26"];
const BAL: LeaveBalance[] = [
  { employee: "Kevin Mutua", type: "Annual", allocated: 21, taken: 9, booked: 3 },
  { employee: "Kevin Mutua", type: "Sick", allocated: 14, taken: 2, booked: 0 },
  { employee: "Faith Njeri", type: "Annual", allocated: 21, taken: 19, booked: 2 },
];
const BOOKED = [{ employee: "Kevin Mutua", from: "2026-11-23", to: "2026-11-25" }];

function LeaveDemo() {
  const [r, setR] = React.useState({ employee: "Kevin Mutua", type: "Annual", from: "2026-11-16", to: "2026-11-24" });
  const [tried, setTried] = React.useState(false);
  const bal = BAL.find((b) => b.employee === r.employee && b.type === r.type);
  const { days, problems } = leaveProblems(r, bal, BOOKED, HOLIDAYS);
  return (
    <Example title="Leave" description="Balances per employee and type. A request counts working days (no weekends or public holidays) and is checked against what's left and leave already booked">
      <div className="space-y-4">
        <p className="text-xs text-muted-foreground">Types: Annual 21 days, Sick 14 days, Maternity 90 days, Paternity 14 days (paid). Mashujaa Day, 20 Oct, is a public holiday.</p>
        <LeaveBalances rows={BAL} />
        <div className="grid gap-3 sm:grid-cols-4">
          <Field>
            <FieldLabel htmlFor="lv-emp">Employee</FieldLabel>
            <NativeSelect id="lv-emp" value={r.employee} onChange={(e) => setR({ ...r, employee: e.target.value })}>
              <NativeSelectOption>Kevin Mutua</NativeSelectOption>
              <NativeSelectOption>Faith Njeri</NativeSelectOption>
            </NativeSelect>
          </Field>
          <Field>
            <FieldLabel htmlFor="lv-type">Leave</FieldLabel>
            <NativeSelect id="lv-type" value={r.type} onChange={(e) => setR({ ...r, type: e.target.value })}>
              <NativeSelectOption>Annual</NativeSelectOption>
              <NativeSelectOption>Sick</NativeSelectOption>
            </NativeSelect>
          </Field>
          <Field>
            <FieldLabel htmlFor="lv-from">First day</FieldLabel>
            <Input id="lv-from" type="date" value={r.from} onChange={(e) => setR({ ...r, from: e.target.value })} />
          </Field>
          <Field>
            <FieldLabel htmlFor="lv-to">Last day</FieldLabel>
            <Input id="lv-to" type="date" value={r.to} onChange={(e) => setR({ ...r, to: e.target.value })} />
          </Field>
        </div>
        <p className="text-sm tabular-nums">
          {days} working {days === 1 ? "day" : "days"}
          {bal ? `; ${Math.max(0, bal.allocated - bal.taken - bal.booked)} left` : ""}.
        </p>
        {tried && problems.length ? (
          <ul role="alert" className="list-disc rounded-md border border-status-error-border bg-status-error-bg py-2 pr-3 pl-8 text-sm text-status-error-text">
            {problems.map((p) => (
              <li key={p}>{p}</li>
            ))}
          </ul>
        ) : null}
        <div className="flex justify-end">
          <Button
            onClick={() => {
              setTried(true);
              if (!problems.length) toast.add({ title: "Leave booked", description: `${days} days of ${r.type.toLowerCase()} leave for ${r.employee}.` });
            }}
          >
            Book leave
          </Button>
        </div>
      </div>
    </Example>
  );
}

const ITEMS: PayItem[] = [
  { id: "i1", employee: "Kevin Mutua", kind: "Allowance", category: "Transport", amount: 4000, recurring: true, from: "2026-01", taxable: true },
  { id: "i2", employee: "Grace Wanjiru", kind: "Allowance", category: "House", amount: 15000, recurring: true, from: "2025-06", taxable: true },
  { id: "i3", employee: "Faith Njeri", kind: "Allowance", category: "Night shift", amount: 2500, recurring: false, from: "2026-10", taxable: true },
  { id: "i4", employee: "Kevin Mutua", kind: "Deduction", category: "Welfare (SACCO)", amount: 1000, recurring: true, from: "2026-03" },
  { id: "i5", employee: "Faith Njeri", kind: "Deduction", category: "Uniform", amount: 1500, recurring: true, from: "2026-07", until: "2026-09" },
  { id: "i6", employee: "Peter Kamau", kind: "Allowance", category: "Meals", amount: 3000, recurring: false, from: "2026-09", taxable: false },
];

const RUN: RunEmployee[] = [
  { name: "Grace Wanjiru", department: "Dispensary", kind: "Monthly", gross: 110000, paye: 22684.85, net: 78320.15, phone: "0712000111", email: "grace@medora.co.ke" },
  { name: "Faith Njeri", department: "Dispensary", kind: "Monthly", gross: 50000, paye: 5845.85, net: 39029.15, phone: "0110222333" },
  { name: "Kevin Mutua", department: "Front shop", kind: "Monthly", gross: 39500, paye: 3018.73, net: 32432.52, phone: "0722000214" },
  { name: "Peter Kamau", department: "Admin", kind: "Monthly", gross: 140000, paye: 31302.35, net: 98427.65, email: "peter@medora.co.ke" },
  { name: "Ali Hassan", department: "Delivery", kind: "Casuals", gross: 2200, paye: 0, net: 2200, phone: "0733000111" },
  { name: "Mercy Atieno", department: "Stores", kind: "Piece workers", gross: 6400, paye: 0, net: 6400 },
];

function PayrollRunsDemo() {
  const [kind, setKind] = React.useState<RunKind>("Monthly");
  const [selected, setSelected] = React.useState<Set<string>>(new Set(RUN.filter((r) => r.kind === "Monthly").map((r) => r.name)));
  const [view, setView] = React.useState<"grouped" | "summary">("grouped");
  const [approved, setApproved] = React.useState(true);
  const [reversing, setReversing] = React.useState(false);
  const [channel, setChannel] = React.useState<"SMS" | "Email">("Email");
  const pool = RUN.filter((r) => r.kind === kind);
  const rows = pool.filter((r) => selected.has(r.name));
  const missing = unreachable(rows, channel);
  return (
    <Example title="Payroll runs and payslips" description="Run monthly staff, piece workers (by date range) or casuals (from unpaid time logs), for all or some. Payslips show grouped by department or as a summary, and go out by SMS or email. An approved run can only be reversed and re-run" bare>
      <div className="space-y-4 p-4">
        <div className="flex flex-wrap items-end gap-3">
          <Field className="w-48">
            <FieldLabel htmlFor="run-kind">Run</FieldLabel>
            <NativeSelect
              id="run-kind"
              value={kind}
              onChange={(e) => {
                const k = e.target.value as RunKind;
                setKind(k);
                setSelected(new Set(RUN.filter((r) => r.kind === k).map((r) => r.name)));
              }}
            >
              <NativeSelectOption>Monthly</NativeSelectOption>
              <NativeSelectOption>Piece workers</NativeSelectOption>
              <NativeSelectOption>Casuals</NativeSelectOption>
            </NativeSelect>
          </Field>
          <span className="pb-2 text-sm text-muted-foreground">{kind === "Monthly" ? "October 2026, all departments" : kind === "Piece workers" ? "1–20 Oct 2026" : "Unpaid time logs to 20 Oct"}</span>
        </div>
        <fieldset className="flex flex-wrap gap-x-4 gap-y-1 text-sm">
          <legend className="mb-1 text-sm font-medium">
            Include ({selected.size} of {pool.length})
          </legend>
          {pool.map((r) => (
            <label key={r.name} className="inline-flex items-center gap-1.5">
              <Checkbox
                checked={selected.has(r.name)}
                onCheckedChange={(v) =>
                  setSelected((s) => {
                    const n = new Set(s);
                    if (v) n.add(r.name);
                    else n.delete(r.name);
                    return n;
                  })
                }
              />
              {r.name}
            </label>
          ))}
        </fieldset>
        <div className="flex flex-wrap items-center gap-3">
          <ToggleGroup variant="outline" size="sm" spacing={0} aria-label="Payslip view" value={[view]} onValueChange={(v: string[]) => v[0] && setView(v[0] as "grouped" | "summary")}>
            <ToggleGroupItem value="grouped">Grouped</ToggleGroupItem>
            <ToggleGroupItem value="summary">Summary</ToggleGroupItem>
          </ToggleGroup>
          {kind === "Monthly" ? <span className={approved ? "text-xs font-medium text-status-success-text" : "text-xs text-muted-foreground"}>{approved ? "PAY-2026-10 approved: locked" : "PAY-2026-10 reversed: edit and re-run"}</span> : null}
        </div>
        {view === "grouped" ? (
          <PayslipGroups rows={rows} />
        ) : (
          <dl className="grid grid-cols-2 gap-px overflow-hidden rounded-lg border border-[var(--color-border-panel)] bg-[var(--color-border-panel)] text-sm sm:grid-cols-4">
            {[
              ["Employees", String(rows.length)],
              ["Gross", n2(rows.reduce((s, r) => s + r.gross, 0))],
              ["PAYE", n2(rows.reduce((s, r) => s + r.paye, 0))],
              ["Net to pay", n2(rows.reduce((s, r) => s + r.net, 0))],
            ].map(([k, v]) => (
              <div key={k} className="bg-card px-3 py-2">
                <dt className="text-xs text-muted-foreground">{k}</dt>
                <dd className="font-semibold tabular-nums">{v}</dd>
              </div>
            ))}
          </dl>
        )}
        <div className="flex flex-wrap items-center gap-2">
          <NativeSelect size="sm" aria-label="Send payslips by" value={channel} onChange={(e) => setChannel(e.target.value as "SMS" | "Email")}>
            <NativeSelectOption>Email</NativeSelectOption>
            <NativeSelectOption>SMS</NativeSelectOption>
          </NativeSelect>
          <Button size="sm" variant="outline" disabled={!rows.length || (kind === "Monthly" && !approved)} onClick={() => toast.add({ title: `${rows.length - missing.length} payslips sent by ${channel}`, description: missing.length ? `Not sent to ${missing.map((m) => m.name).join(", ")}: no ${channel === "SMS" ? "mobile number" : "email"} on file.` : undefined })}>
            {channel === "SMS" ? <MessageSquareIcon data-icon="inline-start" /> : <MailIcon data-icon="inline-start" />}
            Send payslips
          </Button>
          {missing.length ? <span className="text-xs text-status-warning-text">{missing.length} without {channel === "SMS" ? "a mobile number" : "an email"}: {missing.map((m) => m.name).join(", ")}</span> : null}
          {kind === "Monthly" && approved ? (
            <Button size="sm" variant="ghost" className="ml-auto text-status-error-text" onClick={() => setReversing(true)}>
              Reverse run…
            </Button>
          ) : null}
        </div>
      </div>
      <ConfirmDialog
        open={reversing}
        onOpenChange={setReversing}
        level="C"
        title="Reverse payroll run PAY-2026-10?"
        consequences={["Its ledger postings are reversed and its payslips marked void.", "Advances and loan instalments it recovered go back to outstanding.", "Then fix and run October again."]}
        confirmText="PAY-2026-10"
        reasons={["Wrong hours or rates", "Employee missed out", "Statutory rate wrong", "Other"]}
        actionLabel="Reverse run"
        onConfirm={() => setApproved(false)}
      />
    </Example>
  );
}

export function HrMoreSection() {
  return (
    <Section id="hr-more" title="Employees, leave, allowances and payroll runs" description="Staff records and what flows into each payroll: who they are and how they're paid, leave and its balances, recurring and one-off allowances and deductions, and running, viewing, sending and reversing payroll.">
      <EmployeeDemo />
      <LeaveDemo />
      <Example title="Allowances and deductions" description="Recurring or one-off; what's included in the October 2026 payroll and why">
        <PayItemsTable items={ITEMS} month="2026-10" />
      </Example>
      <PayrollRunsDemo />
    </Section>
  );
}
