"use client";

import * as React from "react";

import { kes } from "@/components/medora/payroll";
import { ListTable } from "@/components/medora/record-lists";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";
import { cn } from "@/lib/utils";

/*
 * Bonuses (HR-17): recorded per employee with month, type and description, and paid in that month's
 * payroll. A month whose payroll is already approved is closed: a late bonus goes into the next open month
 * rather than reopening an approved run (HR-06).
 */

export const BONUS_TYPES = ["Performance", "Festive", "Referral", "Long service", "Other"] as const;
export type Bonus = { id: string; employee: string; month: string; type: (typeof BONUS_TYPES)[number]; description: string; amount: number };
export type BonusDraft = { employee: string; month: string; type: Bonus["type"] | ""; description: string; amount: string };

const monthLabel = (m: string) => `${["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][Number(m.slice(5, 7)) - 1]} ${m.slice(0, 4)}`;

export function bonusProblems(d: BonusDraft, closedMonths: string[]) {
  const p: Partial<Record<keyof BonusDraft, string>> = {};
  if (!d.employee) p.employee = "Choose the employee.";
  if (!d.month) p.month = "Choose the payroll month.";
  else if (closedMonths.includes(d.month)) p.month = `${monthLabel(d.month)} payroll is approved. Pay it in the next open month.`;
  if (!d.type) p.type = "Choose the type.";
  if (!d.description.trim()) p.description = "Say what it's for; it prints on the payslip.";
  if (!/^\d+(\.\d{1,2})?$/.test(d.amount.replace(/,/g, "")) || Number(d.amount.replace(/,/g, "")) <= 0) p.amount = "Enter the amount (taxable with salary).";
  return p;
}

export function BonusForm({ d, onChange, employees, months, closedMonths, problems, show }: { d: BonusDraft; onChange: (d: BonusDraft) => void; employees: string[]; months: string[]; closedMonths: string[]; problems: Partial<Record<keyof BonusDraft, string>>; show: boolean }) {
  const P = show ? problems : {};
  const set = <K extends keyof BonusDraft>(k: K, v: BonusDraft[K]) => onChange({ ...d, [k]: v });
  const f = (k: keyof BonusDraft, label: string, node: React.ReactNode) => (
    <div className="space-y-1" data-invalid={!!P[k] || undefined}>
      <label htmlFor={`bn-${k}`} className="text-sm font-medium">
        {label}
      </label>
      {node}
      {P[k] ? <p className="text-xs text-status-error-text">{P[k]}</p> : null}
    </div>
  );
  return (
    <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-5">
      {f(
        "employee",
        "Employee",
        <NativeSelect id="bn-employee" value={d.employee} onChange={(e) => set("employee", e.target.value)} aria-invalid={!!P.employee}>
          <NativeSelectOption value="">Choose…</NativeSelectOption>
          {employees.map((e) => (
            <NativeSelectOption key={e}>{e}</NativeSelectOption>
          ))}
        </NativeSelect>,
      )}
      {f(
        "month",
        "Paid in",
        <NativeSelect id="bn-month" value={d.month} onChange={(e) => set("month", e.target.value)} aria-invalid={!!P.month}>
          <NativeSelectOption value="">Month…</NativeSelectOption>
          {months.map((m) => (
            <NativeSelectOption key={m} value={m}>
              {monthLabel(m)}
              {closedMonths.includes(m) ? " (approved)" : ""}
            </NativeSelectOption>
          ))}
        </NativeSelect>,
      )}
      {f(
        "type",
        "Type",
        <NativeSelect id="bn-type" value={d.type} onChange={(e) => set("type", e.target.value as BonusDraft["type"])} aria-invalid={!!P.type}>
          <NativeSelectOption value="">Choose…</NativeSelectOption>
          {BONUS_TYPES.map((t) => (
            <NativeSelectOption key={t}>{t}</NativeSelectOption>
          ))}
        </NativeSelect>,
      )}
      {f("description", "What it's for", <Input id="bn-description" value={d.description} onChange={(e) => set("description", e.target.value)} aria-invalid={!!P.description} />)}
      {f("amount", "Amount (KES)", <Input id="bn-amount" inputMode="decimal" className="tabular-nums" value={d.amount} onChange={(e) => set("amount", e.target.value)} aria-invalid={!!P.amount} />)}
    </div>
  );
}

/** Bonuses by month: paid ones are in an approved run and can't be removed; pending ones can. */
export function BonusList({ bonuses, closedMonths, onRemove }: { bonuses: Bonus[]; closedMonths: string[]; onRemove: (id: string) => void }) {
  return (
    <ListTable
      rows={[...bonuses].sort((a, b) => b.month.localeCompare(a.month))}
      rowKey={(b) => b.id}
      filters={[
        { label: "Month", all: "All months", value: (b) => monthLabel(b.month) },
        { label: "Type", all: "All types", value: (b) => b.type },
      ]}
      cols={[
        { key: "e", header: "Employee", cell: (b) => b.employee },
        { key: "m", header: "Paid in", cell: (b) => monthLabel(b.month) },
        { key: "t", header: "Type and reason", cell: (b) => (<>{b.type}<span className="block text-xs text-muted-foreground">{b.description}</span></>) },
        { key: "s", header: "Status", cell: (b) => <span className={cn("rounded px-1.5 py-0.5 text-[11px] font-medium", closedMonths.includes(b.month) ? "bg-status-success-bg text-status-success-text" : "bg-muted text-muted-foreground")}>{closedMonths.includes(b.month) ? "Paid" : "In next payroll"}</span> },
        { key: "a", header: "Amount", numeric: true, cell: (b) => kes(b.amount), total: (s) => kes(s.reduce((t, b) => t + b.amount, 0)) },
        { key: "x", header: "", cell: (b) => (closedMonths.includes(b.month) ? null : <Button size="sm" variant="ghost" onClick={() => onRemove(b.id)}>Remove</Button>) },
      ]}
      totalsLabel={(s) => `${s.length} bonuses`}
    />
  );
}
