'use client';

import Link from 'next/link';
import { format } from 'date-fns';
import { MoreHorizontal, Pencil, Archive, Mail, Phone } from 'lucide-react';
import { WhatsAppIcon } from '@/components/icons/whatsapp';
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 { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { getCountryName } from '@/lib/i18n/countries';
import { stageDotClass, stageLabel, formatSource, formatOutcome } from '@/lib/constants';
import { cn } from '@/lib/utils';
import type { ColumnPickerOption } from '@/components/shared/column-picker';

export interface ClientRow {
  id: string;
  fullName: string;
  nationalityIso: string | null;
  source: string | null;
  archivedAt: string | null;
  createdAt: string;
  primaryEmail?: string | null;
  primaryPhone?: string | null;
  /** E.164 (digits + leading +) — used to build wa.me / tel: links. */
  primaryPhoneE164?: string | null;
  yachtCount?: number;
  companyCount?: number;
  interestCount?: number;
  latestInterest?: { stage: string; mooringNumber: string | null } | null;
  /**
   * Berths the client has interests in (active only) with the most-active
   * interest's stage attached. Sorted server-side: open deals first, most
   * progressed stage first, then mooring alphabetical. Each chip in the
   * list view links to the interest, not the berth — that's the action
   * sales reps want.
   */
  linkedBerths?: Array<{
    id: string;
    mooringNumber: string;
    interestId: string;
    stage: string;
    outcome: string | null;
  }>;
  tags?: Array<{ id: string; name: string; color: string }>;
}

/**
 * Picker manifest — drives the `<ColumnPicker>` dropdown next to the
 * filter bar. Order here is the order shown in the menu. `alwaysVisible`
 * marks columns the user can't hide (otherwise the table is unusable).
 *
 * "Latest stage" used to be a default-on column, but each Berths chip
 * now carries its own per-interest stage (color dot + label), so the
 * standalone column was duplicating the same information. Kept in the
 * picker for users who want a single coarse "what's their most recent
 * stage" indicator regardless of berth.
 */
export const CLIENT_COLUMN_OPTIONS: ColumnPickerOption[] = [
  { id: 'fullName', label: 'Name', alwaysVisible: true },
  { id: 'email', label: 'Email' },
  { id: 'phone', label: 'Phone' },
  { id: 'country', label: 'Country' },
  { id: 'source', label: 'Source' },
  { id: 'berths', label: 'Berths' },
  { id: 'latestStage', label: 'Latest stage (legacy)' },
  { id: 'createdAt', label: 'Created' },
];

/**
 * Default-hidden columns for a fresh user. The hook merges this with
 * the user's saved overrides — once they explicitly toggle a column,
 * their choice wins. New columns surface for existing users by default
 * (they're absent from the user's stored hidden list).
 */
export const CLIENT_DEFAULT_HIDDEN: string[] = ['latestStage'];

interface GetColumnsOptions {
  portSlug: string;
  onEdit: (client: ClientRow) => void;
  onArchive: (client: ClientRow) => void;
}

export function getClientColumns({
  portSlug,
  onEdit,
  onArchive,
}: GetColumnsOptions): ColumnDef<ClientRow, unknown>[] {
  return [
    {
      id: 'fullName',
      accessorKey: 'fullName',
      header: 'Name',
      cell: ({ row }) => (
        <Link
          href={`/${portSlug}/clients/${row.original.id}`}
          className="font-medium text-primary hover:underline"
          onClick={(e) => e.stopPropagation()}
        >
          {row.original.fullName}
        </Link>
      ),
    },
    {
      id: 'email',
      header: 'Email',
      enableSorting: false,
      cell: ({ row }) => {
        const value = row.original.primaryEmail;
        if (!value) return <span className="text-muted-foreground">-</span>;
        return (
          <a
            href={`mailto:${value}`}
            onClick={(e) => e.stopPropagation()}
            className="inline-flex items-center gap-1.5 text-sm text-foreground hover:text-primary hover:underline"
            title={`Email ${value}`}
          >
            <Mail className="h-3 w-3 shrink-0 text-muted-foreground" aria-hidden />
            <span className="truncate">{value}</span>
          </a>
        );
      },
    },
    {
      id: 'phone',
      header: 'Phone',
      enableSorting: false,
      cell: ({ row }) => {
        const value = row.original.primaryPhone;
        const e164 = row.original.primaryPhoneE164;
        if (!value) return <span className="text-muted-foreground">-</span>;
        // wa.me requires the E.164 digits without the leading +; fall
        // back to a tel: link when the contact hasn't been normalized
        // yet (legacy rows imported before the i18n PhoneInput shipped).
        const waDigits = e164 ? e164.replace(/[^0-9]/g, '') : null;
        return (
          <span className="inline-flex items-center gap-1.5 text-sm">
            <a
              href={e164 ? `tel:${e164}` : `tel:${value}`}
              onClick={(e) => e.stopPropagation()}
              className="inline-flex items-center gap-1.5 text-foreground hover:text-primary hover:underline"
              title={`Call ${value}`}
            >
              <Phone className="h-3 w-3 shrink-0 text-muted-foreground" aria-hidden />
              <span>{value}</span>
            </a>
            {waDigits && (
              <a
                href={`https://wa.me/${waDigits}`}
                target="_blank"
                rel="noopener noreferrer"
                onClick={(e) => e.stopPropagation()}
                className="text-emerald-600 hover:text-emerald-700"
                title={`WhatsApp ${value}`}
                aria-label={`WhatsApp ${value}`}
              >
                <WhatsAppIcon className="h-3.5 w-3.5" />
              </a>
            )}
          </span>
        );
      },
    },
    {
      id: 'country',
      accessorKey: 'nationalityIso',
      header: 'Country',
      cell: ({ getValue }) => {
        const iso = getValue() as string | null;
        return (
          <span className="text-muted-foreground">{iso ? getCountryName(iso, 'en') : '-'}</span>
        );
      },
    },
    {
      id: 'source',
      accessorKey: 'source',
      header: 'Source',
      cell: ({ getValue }) => {
        const source = getValue() as string | null;
        const label = formatSource(source);
        if (!label) return <span className="text-muted-foreground">-</span>;
        return (
          <Badge variant="outline" className="capitalize text-xs">
            {label}
          </Badge>
        );
      },
    },
    {
      id: 'berths',
      header: 'Berths',
      enableSorting: false,
      cell: ({ row }) => {
        const list = row.original.linkedBerths ?? [];
        if (list.length === 0) return <span className="text-muted-foreground">-</span>;
        // Show the 2 most-actionable interests inline (sorted server-
        // side: open before closed, most-progressed stage first). The
        // remainder collapses behind a "+N" popover so the row stays
        // single-line even for clients with many historical interests.
        const VISIBLE = 2;
        const head = list.slice(0, VISIBLE);
        const overflow = list.slice(VISIBLE);
        return (
          <div className="flex flex-wrap items-center gap-1">
            {head.map((b) => (
              <BerthInterestChip key={b.id} berth={b} portSlug={portSlug} />
            ))}
            {overflow.length > 0 && (
              <Popover>
                <PopoverTrigger asChild>
                  <button
                    type="button"
                    onClick={(e) => e.stopPropagation()}
                    className="rounded-full border border-border bg-background px-2 py-0.5 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-foreground transition-colors"
                  >
                    +{overflow.length}
                  </button>
                </PopoverTrigger>
                <PopoverContent
                  align="start"
                  className="w-64 p-1"
                  onClick={(e) => e.stopPropagation()}
                >
                  <div className="px-2 py-1.5 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
                    All linked berths
                  </div>
                  <div className="space-y-0.5">
                    {list.map((b) => (
                      <Link
                        key={b.id}
                        href={`/${portSlug}/interests/${b.interestId}`}
                        onClick={(e) => e.stopPropagation()}
                        className="flex items-center gap-2 rounded px-2 py-1.5 text-sm hover:bg-accent"
                      >
                        <span
                          aria-hidden
                          className={cn(
                            'h-2 w-2 shrink-0 rounded-full',
                            b.outcome ? 'bg-muted-foreground/40' : stageDotClass(b.stage),
                          )}
                        />
                        <span className="font-medium text-foreground">{b.mooringNumber}</span>
                        <span className="text-xs text-muted-foreground">
                          {b.outcome
                            ? `${stageLabel(b.stage)} · ${formatOutcome(b.outcome) ?? b.outcome}`
                            : stageLabel(b.stage)}
                        </span>
                      </Link>
                    ))}
                  </div>
                </PopoverContent>
              </Popover>
            )}
          </div>
        );
      },
    },
    {
      // Hidden by default — the per-berth stage is now carried by each
      // chip in the Berths column, so this standalone column is only
      // useful when a user has explicitly toggled it on.
      id: 'latestStage',
      header: 'Latest stage',
      enableSorting: false,
      cell: ({ row }) => {
        const latest = row.original.latestInterest;
        if (!latest) return <span className="text-muted-foreground">-</span>;
        return (
          <Badge variant="secondary" className="text-xs">
            {stageLabel(latest.stage)}
          </Badge>
        );
      },
    },
    {
      id: 'createdAt',
      accessorKey: 'createdAt',
      header: 'Created',
      cell: ({ getValue }) => (
        <span className="text-muted-foreground text-sm">
          {format(new Date(getValue() as string), 'MMM d, yyyy')}
        </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.fullName ?? 'client'}`}
              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>
      ),
    },
  ];
}

/**
 * Single berth-with-stage chip used in the inline (top-2) chip row of
 * the Berths column. Shows mooring + full stage label, with a colored
 * dot for stage reinforcement (decorative — the label carries the
 * meaning so color-blind / no-hover users don't lose anything).
 *
 * Click target is the *interest*, not the berth — the user almost
 * always wants to act on the deal, not look at the berth's static
 * specs. Outcome-set rows (won/lost/cancelled) get a muted dot so they
 * read as historical context rather than active work.
 */
function BerthInterestChip({
  berth,
  portSlug,
}: {
  berth: NonNullable<ClientRow['linkedBerths']>[number];
  portSlug: string;
}) {
  const isClosed = berth.outcome !== null;
  const label = isClosed
    ? `${stageLabel(berth.stage)} · ${formatOutcome(berth.outcome) ?? berth.outcome}`
    : stageLabel(berth.stage);
  return (
    <Link
      href={`/${portSlug}/interests/${berth.interestId}`}
      onClick={(e) => e.stopPropagation()}
      title={`Open interest · ${berth.mooringNumber} · ${label}`}
      className={cn(
        'inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs transition-colors',
        'border-border bg-background hover:bg-accent',
        isClosed && 'opacity-60',
      )}
    >
      <span
        aria-hidden
        className={cn(
          'h-2 w-2 shrink-0 rounded-full',
          isClosed ? 'bg-muted-foreground/40' : stageDotClass(berth.stage),
        )}
      />
      <span className="font-medium text-foreground">{berth.mooringNumber}</span>
      <span className="text-muted-foreground">·</span>
      <span className="text-muted-foreground">{label}</span>
    </Link>
  );
}
