'use client';

/**
 * Bulk berth price-reconcile table (CM-2 Part A).
 *
 * Lists the price parsed from each berth's current spec sheet next to the stored
 * price, with per-row + select-all approval. Nothing is written until the rep
 * approves — the apply mutation posts only the checked, changed rows.
 */

import { useMemo, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';

import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { EmptyState } from '@/components/ui/empty-state';

interface Row {
  berthId: string;
  mooringNumber: string;
  area: string | null;
  currentPrice: number | null;
  currentCurrency: string;
  parsedPrice: number | null;
  parsedCurrency: string | null;
  status: 'changed' | 'matched' | 'needs_review' | 'no_pdf';
  warning?: string;
}

const STATUS_STYLE: Record<Row['status'], string> = {
  changed: 'bg-amber-100 text-amber-800',
  matched: 'bg-muted text-muted-foreground',
  needs_review: 'bg-red-100 text-red-700',
  no_pdf: 'bg-slate-100 text-slate-500',
};
const STATUS_LABEL: Record<Row['status'], string> = {
  changed: 'Changed',
  matched: 'Matched',
  needs_review: 'Needs review',
  no_pdf: 'No PDF',
};

const fmt = (n: number | null, ccy: string | null) =>
  n == null ? '—' : `${n.toLocaleString()} ${ccy ?? ''}`.trim();

export function BerthPriceReconcileTable() {
  const qc = useQueryClient();
  const { data, isLoading } = useQuery<{ data: Row[] }>({
    queryKey: ['berths', 'price-reconcile'],
    queryFn: () => apiFetch('/api/v1/berths/price-reconcile'),
  });
  const rows = useMemo(() => data?.data ?? [], [data]);
  const selectable = useMemo(() => rows.filter((r) => r.status === 'changed'), [rows]);
  const [checked, setChecked] = useState<Record<string, boolean>>({});

  const apply = useMutation({
    mutationFn: async (): Promise<{ data: { updated: number } }> => {
      const approvals = selectable
        .filter((r) => checked[r.berthId] && r.parsedPrice != null)
        .map((r) => ({
          berthId: r.berthId,
          price: r.parsedPrice as number,
          currency: r.parsedCurrency ?? r.currentCurrency,
        }));
      return apiFetch('/api/v1/berths/price-reconcile/apply', {
        method: 'POST',
        body: { approvals },
      });
    },
    onSuccess: (res) => {
      toast.success(`Updated ${res.data.updated} berth price(s).`);
      setChecked({});
      void qc.invalidateQueries({ queryKey: ['berths'] });
    },
    onError: (e: Error) => toastError(e),
  });

  if (isLoading) {
    return <p className="p-6 text-sm text-muted-foreground">Parsing spec sheets…</p>;
  }

  if (rows.length === 0) {
    return (
      <EmptyState title="No berths to reconcile" body="No active berths found for this port." />
    );
  }

  const allChecked = selectable.length > 0 && selectable.every((r) => checked[r.berthId]);
  const selectedCount = selectable.filter((r) => checked[r.berthId]).length;
  const reviewCount = rows.filter((r) => r.status === 'needs_review').length;
  const noPdfCount = rows.filter((r) => r.status === 'no_pdf').length;

  return (
    <div className="space-y-3">
      <div className="flex flex-wrap items-center justify-between gap-2">
        <p className="text-sm text-muted-foreground">
          {selectable.length} changed · {reviewCount} need review · {noPdfCount} without a PDF
        </p>
        <Button
          size="sm"
          disabled={selectedCount === 0 || apply.isPending}
          onClick={() => apply.mutate()}
        >
          {apply.isPending ? 'Applying…' : `Approve selected (${selectedCount})`}
        </Button>
      </div>

      <div className="overflow-hidden rounded-md border bg-white">
        <table className="w-full text-sm">
          <thead>
            <tr className="border-b bg-muted/30 text-start text-xs text-muted-foreground">
              <th className="w-10 p-2 ps-3">
                <Checkbox
                  aria-label="Select all changed"
                  checked={allChecked}
                  onCheckedChange={(c) =>
                    setChecked(
                      c === true
                        ? Object.fromEntries(selectable.map((r) => [r.berthId, true]))
                        : {},
                    )
                  }
                />
              </th>
              <th className="p-2">Mooring</th>
              <th className="p-2">Area</th>
              <th className="p-2 text-end">Current</th>
              <th className="p-2 text-end">Parsed</th>
              <th className="p-2">Status</th>
            </tr>
          </thead>
          <tbody>
            {rows.map((r) => (
              <tr key={r.berthId} className="border-b last:border-0">
                <td className="p-2 ps-3">
                  {r.status === 'changed' ? (
                    <Checkbox
                      aria-label={`Approve ${r.mooringNumber}`}
                      checked={!!checked[r.berthId]}
                      onCheckedChange={(c) =>
                        setChecked((p) => ({ ...p, [r.berthId]: c === true }))
                      }
                    />
                  ) : null}
                </td>
                <td className="p-2 font-medium">{r.mooringNumber}</td>
                <td className="p-2 text-muted-foreground">{r.area ?? '—'}</td>
                <td className="p-2 text-end tabular-nums">
                  {fmt(r.currentPrice, r.currentCurrency)}
                </td>
                <td className="p-2 text-end tabular-nums">
                  {fmt(r.parsedPrice, r.parsedCurrency)}
                </td>
                <td className="p-2">
                  <span className={`rounded px-2 py-0.5 text-xs ${STATUS_STYLE[r.status]}`}>
                    {STATUS_LABEL[r.status]}
                  </span>
                  {r.warning ? (
                    <span className="ms-2 text-xs text-muted-foreground">{r.warning}</span>
                  ) : null}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}
