'use client';

import Link from 'next/link';
import { format, formatDistanceToNowStrict } from 'date-fns';
import { MoreHorizontal, Pencil, Archive, MessageSquare } from 'lucide-react';
import type { ColumnDef } from '@tanstack/react-table';

import { Button } from '@/components/ui/button';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { Badge } from '@/components/ui/badge';
import { stageBadgeClass, stageLabel } from '@/lib/constants';
import { deriveInterestBerthLabel } from '@/lib/templates/interest-berth-label';
import { computeUrgencyBadges, type InterestUrgencyInput } from '@/components/interests/urgency';

export interface InterestRow {
  id: string;
  clientId: string;
  clientName: string | null;
  yachtId?: string | null;
  yachtName?: string | null;
  berthId: string | null;
  berthMooringNumber: string | null;
  /** Every linked berth's mooring (sorted) - drives the multi-berth list
   *  cell label (`A1-A3, B5`). Falls back to `berthMooringNumber` alone
   *  when empty/absent. */
  berthMoorings?: string[];
  pipelineStage: string;
  leadCategory: string | null;
  source: string | null;
  archivedAt: string | null;
  createdAt: string;
  /** Surfaced by listInterests for the row-level sales-triage signals
   *  (last-activity relative time, comment-icon, urgency badges). */
  updatedAt?: string;
  dateLastContact?: string | null;
  dateEoiSent?: string | null;
  dateDepositReceived?: string | null;
  eoiStatus?: string | null;
  outcome?: string | null;
  /** Imperial; nullable. Recommender treats nulls as "no constraint" on
   *  that axis. Rendered as a compact "60×18×6 ft" string in the list. */
  desiredLengthFt?: string | number | null;
  desiredWidthFt?: string | number | null;
  desiredDraftFt?: string | number | null;
  notesCount?: number;
  tags?: Array<{ id: string; name: string; color: string }>;
}

function formatDim(value: string | number | null | undefined): string {
  if (value === null || value === undefined || value === '') return '?';
  const n = typeof value === 'number' ? value : parseFloat(value);
  if (!Number.isFinite(n)) return '?';
  return Number.isInteger(n) ? String(n) : n.toFixed(1);
}

function formatDesiredSize(row: InterestRow): string | null {
  const { desiredLengthFt, desiredWidthFt, desiredDraftFt } = row;
  if (
    (desiredLengthFt === null || desiredLengthFt === undefined || desiredLengthFt === '') &&
    (desiredWidthFt === null || desiredWidthFt === undefined || desiredWidthFt === '') &&
    (desiredDraftFt === null || desiredDraftFt === undefined || desiredDraftFt === '')
  ) {
    return null;
  }
  return `${formatDim(desiredLengthFt)}×${formatDim(desiredWidthFt)}×${formatDim(desiredDraftFt)} ft`;
}

const SOURCE_LABELS: Record<string, string> = {
  website: 'Website',
  manual: 'Manual',
  referral: 'Referral',
  broker: 'Broker',
};

/**
 * Toggleable columns for the InterestList ColumnPicker. `actions` and
 * `clientName` are intentionally omitted from this list - actions is a
 * row-control column that should never be hidden, and clientName is the
 * primary entity identifier (a row with no name has no useful purpose).
 */
export const INTEREST_COLUMN_OPTIONS: Array<{ id: string; label: string }> = [
  { id: 'yachtName', label: 'Yacht' },
  { id: 'berthMooringNumber', label: 'Berth' },
  { id: 'desiredSize', label: 'Desired size' },
  { id: 'pipelineStage', label: 'Stage' },
  { id: 'eoiStatus', label: 'EOI status' },
  { id: 'source', label: 'Source' },
  { id: 'dateLastContact', label: 'Last contact' },
];

/**
 * Columns hidden by default for users who haven't customised their view.
 * Keep the busy `desiredSize` and `eoiStatus` collapsed by default -
 * power-users can turn them back on via the column picker.
 */
export const INTEREST_DEFAULT_HIDDEN: string[] = ['desiredSize', 'eoiStatus'];

const EOI_STATUS_LABELS: Record<string, { label: string; tone: string }> = {
  waiting_for_signatures: { label: 'Waiting', tone: 'bg-amber-100 text-amber-900' },
  signed: { label: 'Signed', tone: 'bg-emerald-100 text-emerald-900' },
  expired: { label: 'Expired', tone: 'bg-rose-100 text-rose-900' },
};

interface GetColumnsOptions {
  portSlug: string;
  onEdit: (interest: InterestRow) => void;
  onArchive: (interest: InterestRow) => void;
}

export function getInterestColumns({
  portSlug,
  onEdit,
  onArchive,
}: GetColumnsOptions): ColumnDef<InterestRow, unknown>[] {
  return [
    {
      id: 'clientName',
      accessorKey: 'clientName',
      header: 'Client',
      cell: ({ row }) => {
        const notesCount = row.original.notesCount ?? 0;
        return (
          <div className="flex items-center gap-1.5 min-w-0">
            {/* Client cell on the Interests list links to the INTEREST detail
                - not the client page. Users browsing the interest list want
                the deal context, not the underlying client. The interest
                detail header has its own "Client page" deep-link if the rep
                actually wants the client surface. */}
            <Link
              href={`/${portSlug}/interests/${row.original.id}`}
              className="truncate font-medium text-primary hover:underline"
              onClick={(e) => e.stopPropagation()}
            >
              {row.original.clientName ?? '-'}
            </Link>
            {notesCount > 0 ? (
              <span
                title={`${notesCount} note${notesCount === 1 ? '' : 's'}`}
                aria-label={`${notesCount} note${notesCount === 1 ? '' : 's'}`}
                className="inline-flex items-center text-muted-foreground"
              >
                <MessageSquare className="size-3.5" aria-hidden />
              </span>
            ) : null}
          </div>
        );
      },
    },
    {
      id: 'yachtName',
      accessorKey: 'yachtName',
      header: 'Yacht',
      enableSorting: false,
      cell: ({ row }) => {
        const name = row.original.yachtName;
        if (!name) return <span className="text-muted-foreground">-</span>;
        const yachtId = row.original.yachtId;
        if (!yachtId) return <span className="truncate text-sm">{name}</span>;
        return (
          <Link
            href={`/${portSlug}/yachts/${yachtId}`}
            className="truncate text-primary hover:underline text-sm"
            onClick={(e) => e.stopPropagation()}
          >
            {name}
          </Link>
        );
      },
    },
    {
      id: 'berthMooringNumber',
      accessorKey: 'berthMooringNumber',
      header: 'Berth',
      cell: ({ row }) => {
        const label =
          deriveInterestBerthLabel(row.original.berthMoorings) ?? row.original.berthMooringNumber;
        if (!row.original.berthId || !label) {
          return <span className="text-muted-foreground">-</span>;
        }
        return (
          <Link
            href={`/${portSlug}/berths/${row.original.berthId}`}
            className="text-primary hover:underline text-sm"
            onClick={(e) => e.stopPropagation()}
          >
            {label}
          </Link>
        );
      },
    },
    {
      id: 'desiredSize',
      header: 'Berth size desired',
      enableSorting: false,
      cell: ({ row }) => {
        const label = formatDesiredSize(row.original);
        if (!label) return <span className="text-muted-foreground">-</span>;
        return <span className="text-sm tabular-nums">{label}</span>;
      },
    },
    {
      id: 'pipelineStage',
      accessorKey: 'pipelineStage',
      header: 'Stage',
      cell: ({ row }) => {
        const stage = row.original.pipelineStage;
        const badges = computeUrgencyBadges(row.original satisfies InterestUrgencyInput);
        return (
          <Link
            href={`/${portSlug}/interests/${row.original.id}`}
            className="flex flex-col gap-1 items-start hover:opacity-80 transition-opacity"
          >
            <span
              className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${stageBadgeClass(stage)}`}
            >
              {stageLabel(stage)}
            </span>
            {badges.length > 0 ? (
              <div className="flex flex-wrap gap-1">
                {badges.map((b) => (
                  <span
                    key={b.id}
                    title={b.detail}
                    aria-label={b.detail}
                    className={`inline-flex items-center rounded-full px-1.5 py-0.5 text-xs font-medium ${b.className}`}
                  >
                    {b.label}
                  </span>
                ))}
              </div>
            ) : null}
          </Link>
        );
      },
    },
    {
      id: 'eoiStatus',
      accessorKey: 'eoiStatus',
      header: 'EOI status',
      enableSorting: false,
      cell: ({ getValue }) => {
        const status = getValue() as string | null;
        if (!status) return <span className="text-muted-foreground">-</span>;
        const meta = EOI_STATUS_LABELS[status];
        return (
          <span
            className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${
              meta?.tone ?? 'bg-muted text-muted-foreground'
            }`}
          >
            {meta?.label ?? status}
          </span>
        );
      },
    },
    {
      id: 'source',
      accessorKey: 'source',
      header: 'Source',
      cell: ({ getValue }) => {
        const source = getValue() as string | null;
        if (!source) return <span className="text-muted-foreground">-</span>;
        return (
          <Badge variant="outline" className="text-xs">
            {SOURCE_LABELS[source] ?? source}
          </Badge>
        );
      },
    },
    {
      // Sales-triage default: prefer the explicit dateLastContact, fall back
      // to updatedAt. Sortable on dateLastContact server-side; the column
      // header label ("Last activity") makes the fallback semantics clear.
      id: 'dateLastContact',
      accessorKey: 'dateLastContact',
      header: 'Last activity',
      cell: ({ row }) => {
        const lastIso = row.original.dateLastContact ?? row.original.updatedAt ?? null;
        if (!lastIso) {
          return <span className="text-muted-foreground text-sm">-</span>;
        }
        const d = new Date(lastIso);
        return (
          <span className="text-muted-foreground text-sm tabular-nums" title={format(d, 'PPpp')}>
            {formatDistanceToNowStrict(d, { addSuffix: true })}
          </span>
        );
      },
    },
    {
      id: 'actions',
      header: '',
      enableSorting: false,
      size: 48,
      cell: ({ row }) => (
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button
              variant="ghost"
              size="icon"
              className="h-7 w-7"
              aria-label={`Row actions for ${row.original.clientName ?? 'interest'}`}
              onClick={(e) => e.stopPropagation()}
            >
              <MoreHorizontal className="h-4 w-4" aria-hidden />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end">
            <DropdownMenuItem onClick={() => onEdit(row.original)}>
              <Pencil className="mr-2 h-3.5 w-3.5" aria-hidden />
              Edit
            </DropdownMenuItem>
            <DropdownMenuItem className="text-destructive" onClick={() => onArchive(row.original)}>
              <Archive className="mr-2 h-3.5 w-3.5" aria-hidden />
              Archive
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      ),
    },
  ];
}
