'use client';

import { useState } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import {
  Pencil,
  Archive,
  Bell,
  RotateCcw,
  Trophy,
  XCircle,
  RefreshCcw,
  MessageSquarePlus,
  AlarmClock,
  User,
} from 'lucide-react';
import { ComposeDialog as ContactLogComposeSheet } from '@/components/interests/interest-contact-log-tab';
import Link from 'next/link';

import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { TagBadge } from '@/components/shared/tag-badge';
import { ArchiveConfirmDialog } from '@/components/shared/archive-confirm-dialog';
import { DetailHeaderStrip } from '@/components/shared/detail-header-strip';
import { PermissionGate } from '@/components/shared/permission-gate';
import { InterestForm } from '@/components/interests/interest-form';
import { ReminderForm } from '@/components/reminders/reminder-form';
import { InlineStagePicker } from '@/components/interests/inline-stage-picker';
import { InterestOutcomeDialog } from '@/components/interests/interest-outcome-dialog';
import { AssignedToChip } from '@/components/interests/assigned-to-chip';
import { MultiEoiChip } from '@/components/interests/multi-eoi-chip';
import { DealPulseChip } from '@/components/interests/deal-pulse-chip';
import { apiFetch } from '@/lib/api/client';
import { useFeatureFlag } from '@/hooks/use-feature-flag';
import { formatOutcome } from '@/lib/constants';
import { deriveInterestBerthLabel } from '@/lib/templates/interest-berth-label';
import { cn } from '@/lib/utils';

const OUTCOME_BADGE: Record<string, { label: string; className: string }> = {
  won: { label: 'Won', className: 'bg-emerald-100 text-emerald-700' },
  lost_other_marina: { label: 'Lost - other marina', className: 'bg-rose-100 text-rose-700' },
  lost_unqualified: { label: 'Lost - unqualified', className: 'bg-rose-100 text-rose-700' },
  lost_no_response: { label: 'Lost - no response', className: 'bg-rose-100 text-rose-700' },
  lost_other: { label: 'Lost - other', className: 'bg-rose-100 text-rose-700' },
  cancelled: { label: 'Cancelled', className: 'bg-slate-200 text-slate-700' },
};

// Catch-all so an unknown outcome (e.g. a future `lost_no_berth` enum) still
// renders as a closed-state badge instead of falling back to the open-state
// stage picker. Lost-* gets a rose tint; everything else gets neutral slate.
function resolveOutcomeBadge(outcome: string | null | undefined) {
  if (!outcome) return null;
  const known = OUTCOME_BADGE[outcome];
  if (known) return known;
  const isLoss = outcome.startsWith('lost');
  return {
    label: formatOutcome(outcome) ?? outcome,
    className: isLoss ? 'bg-rose-100 text-rose-700' : 'bg-slate-200 text-slate-700',
  };
}

const CATEGORY_LABELS: Record<string, string> = {
  general_interest: 'General',
  specific_qualified: 'Specific qualified',
  hot_lead: 'Hot lead',
};

interface InterestDetailHeaderProps {
  portSlug: string;
  interest: {
    id: string;
    clientId: string;
    clientName: string | null;
    /** Primary contact channels resolved from the linked client. The
     *  Email/Call/WhatsApp pills were removed (CM-4); these stay on the payload
     *  for downstream reuse (e.g. proxy comms routing, CM-9). */
    clientPrimaryEmail?: string | null;
    clientPrimaryPhone?: string | null;
    clientPrimaryPhoneE164?: string | null;
    /** Pending/snoozed reminders attached to this interest. Drives the
     *  alarm-bell badge on the header - surfaces follow-ups so the rep
     *  doesn't have to remember to check /reminders. */
    activeReminderCount?: number;
    berthId: string | null;
    berthMooringNumber: string | null;
    /** Every linked berth's mooring (sorted) - drives the multi-berth
     *  header label (`Berth A1-A3, B5`). When absent or empty, falls back
     *  to the primary mooring alone. */
    berthMoorings?: string[];
    yachtId: string | null;
    pipelineStage: string;
    leadCategory: string | null;
    source: string | null;
    notes: string | null;
    reminderEnabled: boolean;
    reminderDays: number | null;
    archivedAt: string | null;
    outcome?: string | null;
    outcomeReason?: string | null;
    dateLastContact?: string | null;
    dateFirstContact?: string | null;
    dateEoiSent?: string | null;
    dateEoiSigned?: string | null;
    dateReservationSigned?: string | null;
    dateContractSent?: string | null;
    dateContractSigned?: string | null;
    dateDepositReceived?: string | null;
    eoiDocStatus?: string | null;
    reservationDocStatus?: string | null;
    contractDocStatus?: string | null;
    /** Activity-log entries in the last 7 days - drives deal-pulse +5 signal. */
    recentActivityCount?: number | null;
    /** Phase 2 risk-signal dates fed into DealPulseChip. */
    dateDocumentDeclined?: string | Date | null;
    dateReservationCancelled?: string | Date | null;
    dateBerthSoldToOther?: string | Date | null;
    /** Sales rep who owns this deal - populated by the AssignedToChip. */
    assignedTo?: string | null;
    assignedToName?: string | null;
    tags?: Array<{ id: string; name: string; color: string }>;
  };
}

function formatLastContactAge(iso: string): string {
  const days = Math.floor((Date.now() - new Date(iso).getTime()) / 86_400_000);
  if (days <= 0) return 'today';
  if (days === 1) return 'yesterday';
  if (days < 30) return `${days}d ago`;
  if (days < 365) return `${Math.floor(days / 30)}mo ago`;
  return `${Math.floor(days / 365)}y ago`;
}

export function InterestDetailHeader({ portSlug, interest }: InterestDetailHeaderProps) {
  const queryClient = useQueryClient();
  const [editOpen, setEditOpen] = useState(false);
  const [archiveOpen, setArchiveOpen] = useState(false);
  const [outcomeDialog, setOutcomeDialog] = useState<null | 'won' | 'lost'>(null);
  // §1.4: Quick log-contact button next to the Email/Call/WhatsApp pills.
  // Opens the same Sheet the Contact log tab uses without forcing the rep
  // to tab-navigate first.
  const [logContactOpen, setLogContactOpen] = useState(false);
  const [reminderOpen, setReminderOpen] = useState(false);
  // (Upload-paper-signed-EOI dialog moved to the EOI tab.)
  // CM-5: assignment UI is hidden when the per-port toggle is off (default).
  const assignmentEnabled = useFeatureFlag('assignment_enabled', false);

  const isArchived = !!interest.archivedAt;
  const outcomeBadge = resolveOutcomeBadge(interest.outcome);
  const isClosed = !!interest.outcome;

  const reopenMutation = useMutation({
    mutationFn: () =>
      apiFetch(`/api/v1/interests/${interest.id}/outcome`, { method: 'DELETE', body: {} }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['interests', interest.id] });
      queryClient.invalidateQueries({ queryKey: ['interests'] });
      // F26: confirm to the user that the action ran - pre-fix the
      // button gave no feedback and reps weren't sure if it took.
      toast.success('Outcome cleared - interest is open again.');
    },
  });

  const archiveMutation = useMutation({
    mutationFn: () => apiFetch(`/api/v1/interests/${interest.id}`, { method: 'DELETE' }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['interests', interest.id] });
      queryClient.invalidateQueries({ queryKey: ['interests'] });
      setArchiveOpen(false);
    },
  });

  const restoreMutation = useMutation({
    mutationFn: () => apiFetch(`/api/v1/interests/${interest.id}/restore`, { method: 'POST' }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['interests', interest.id] });
      queryClient.invalidateQueries({ queryKey: ['interests'] });
      setArchiveOpen(false);
    },
  });

  // Multi-berth header label: prefer the full berth-range derived from
  // every linked mooring, fall back to the primary alone for older
  // payloads that haven't been re-fetched yet.
  const berthDisplayLabel =
    deriveInterestBerthLabel(interest.berthMoorings) ?? interest.berthMooringNumber;

  const meta: Array<{ key: string; node: React.ReactNode }> = [];
  if (berthDisplayLabel) {
    meta.push({
      key: 'berth',
      node: (
        <Link
          href={`/${portSlug}/berths/${interest.berthId}`}
          className="text-foreground hover:underline"
        >
          Berth {berthDisplayLabel}
        </Link>
      ),
    });
  }
  if (interest.leadCategory) {
    meta.push({
      key: 'cat',
      node: <span>{CATEGORY_LABELS[interest.leadCategory] ?? interest.leadCategory}</span>,
    });
  }
  if (interest.source) {
    meta.push({
      key: 'src',
      node: <span className="capitalize">{interest.source}</span>,
    });
  }
  if (interest.dateLastContact) {
    meta.push({
      key: 'last',
      node: (
        <span className="text-foreground/70">
          Last contact {formatLastContactAge(interest.dateLastContact)}
        </span>
      ),
    });
  }

  return (
    <>
      <DetailHeaderStrip>
        <div className="flex items-start gap-2">
          <div className="min-w-0 flex-1 space-y-1.5">
            <div className="flex items-center gap-2 flex-wrap">
              <h1 className="truncate text-lg font-bold text-foreground sm:text-xl">
                {interest.clientName ?? 'Unknown Client'}
              </h1>
              {isArchived && (
                <Badge variant="secondary" className="text-xs">
                  Archived
                </Badge>
              )}
              {outcomeBadge ? (
                <span
                  className={cn(
                    'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium',
                    outcomeBadge.className,
                  )}
                  title={interest.outcomeReason ?? undefined}
                >
                  {outcomeBadge.label}
                </span>
              ) : (
                <PermissionGate
                  resource="interests"
                  action="change_stage"
                  fallback={
                    <span className="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-700">
                      {interest.pipelineStage}
                    </span>
                  }
                >
                  <InlineStagePicker
                    interestId={interest.id}
                    currentStage={interest.pipelineStage}
                    currentYachtId={interest.yachtId}
                    clientId={interest.clientId}
                  />
                </PermissionGate>
              )}
              {(interest.activeReminderCount ?? 0) > 0 ? (
                <span
                  className="inline-flex items-center gap-1 rounded-full border border-amber-200 bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-800"
                  title={`${interest.activeReminderCount} pending reminder${
                    interest.activeReminderCount === 1 ? '' : 's'
                  }`}
                >
                  <AlarmClock className="size-3" aria-hidden />
                  {interest.activeReminderCount}
                </span>
              ) : null}
              {assignmentEnabled ? (
                <PermissionGate resource="interests" action="edit">
                  <AssignedToChip
                    interestId={interest.id}
                    currentAssignedTo={interest.assignedTo ?? null}
                    currentAssignedToName={interest.assignedToName ?? null}
                  />
                </PermissionGate>
              ) : null}
              <MultiEoiChip interestId={interest.id} />
              <DealPulseChip
                interest={{
                  pipelineStage: interest.pipelineStage,
                  outcome: interest.outcome,
                  archivedAt: interest.archivedAt,
                  dateFirstContact: interest.dateFirstContact,
                  dateLastContact: interest.dateLastContact,
                  dateEoiSent: interest.dateEoiSent,
                  dateEoiSigned: interest.dateEoiSigned,
                  dateReservationSigned: interest.dateReservationSigned,
                  dateContractSent: interest.dateContractSent,
                  dateContractSigned: interest.dateContractSigned,
                  dateDepositReceived: interest.dateDepositReceived,
                  eoiDocStatus: interest.eoiDocStatus,
                  reservationDocStatus: interest.reservationDocStatus,
                  contractDocStatus: interest.contractDocStatus,
                  recentActivityCount: interest.recentActivityCount,
                  dateDocumentDeclined: interest.dateDocumentDeclined,
                  dateReservationCancelled: interest.dateReservationCancelled,
                  dateBerthSoldToOther: interest.dateBerthSoldToOther,
                }}
              />
            </div>

            {meta.length > 0 ? (
              <p className="text-xs text-muted-foreground sm:text-sm">
                {meta.map((m, i) => (
                  <span key={m.key}>
                    {i > 0 ? (
                      <span aria-hidden className="mx-1.5">
                        ·
                      </span>
                    ) : null}
                    {m.node}
                  </span>
                ))}
              </p>
            ) : null}

            {interest.tags && interest.tags.length > 0 && (
              <div className="flex flex-wrap gap-1 pt-0.5">
                {interest.tags.map((tag) => (
                  <TagBadge key={tag.id} name={tag.name} color={tag.color} />
                ))}
              </div>
            )}

            {/* CM-4: Email/Call/WhatsApp deep-links removed at client request.
                Client-page link + Log-contact action stay - the rep can still
                jump to the client and record outreach without leaving here. */}
            <div className="flex flex-wrap items-center gap-1.5 pt-1">
              {interest.clientId ? (
                <Button
                  asChild
                  variant="outline"
                  size="sm"
                  className="h-8 gap-1.5 px-2.5 [&_svg]:size-3.5"
                >
                  <Link
                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
                    href={`/${portSlug}/clients/${interest.clientId}` as any}
                    aria-label="Open client page"
                  >
                    <User />
                    Client page
                  </Link>
                </Button>
              ) : null}
              <Button
                variant="outline"
                size="sm"
                className="h-8 gap-1.5 px-2.5 [&_svg]:size-3.5"
                onClick={() => setLogContactOpen(true)}
                aria-label="Log a contact for this interest"
              >
                <MessageSquarePlus />
                Log contact
              </Button>
            </div>
          </div>

          {/* Top-right actions. Won/Lost are sales-critical and read as text
               buttons on desktop; Edit/Archive stay icon-only. On mobile,
               Won/Lost shrink to icon buttons to keep the cluster from
               wrapping. */}
          <div className="flex shrink-0 items-center gap-1">
            <PermissionGate resource="interests" action="change_stage">
              {isClosed ? (
                <button
                  type="button"
                  onClick={() => reopenMutation.mutate()}
                  disabled={reopenMutation.isPending}
                  className={cn(
                    'inline-flex items-center gap-1.5 rounded-md border border-border px-2.5 py-1 text-xs font-medium text-foreground transition-colors',
                    'hover:bg-foreground/5 disabled:opacity-50',
                  )}
                >
                  <RefreshCcw className="size-3.5" aria-hidden />
                  Reopen
                </button>
              ) : (
                <>
                  {/* Mobile: icon-only with title tooltip + colored fill carries
                      the won/lost meaning (green vs rose). Adding a "Won" /
                      "Lost" text label inline blew out the cluster width and
                      forced the Email/Call/WhatsApp action-chip row above to
                      stack vertically - bad trade. From sm up, the full
                      "Mark won" / "Close as lost" labels read clearly. */}
                  <button
                    type="button"
                    onClick={() => setOutcomeDialog('won')}
                    aria-label="Mark as won"
                    title="Mark as won"
                    className={cn(
                      'inline-flex items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium transition-colors sm:px-2.5',
                      'border border-emerald-200 bg-emerald-50 text-emerald-700',
                      'hover:bg-emerald-100',
                    )}
                  >
                    <Trophy className="size-3.5" aria-hidden />
                    <span className="hidden sm:inline">Mark won</span>
                  </button>
                  <button
                    type="button"
                    onClick={() => setOutcomeDialog('lost')}
                    aria-label="Close as lost"
                    title="Close as lost"
                    className={cn(
                      'inline-flex items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium transition-colors sm:px-2.5',
                      'border border-rose-200 text-rose-700',
                      'hover:bg-rose-50',
                    )}
                  >
                    <XCircle className="size-3.5" aria-hidden />
                    <span className="hidden sm:inline">Close as lost</span>
                  </button>
                </>
              )}
            </PermissionGate>
            {/* The "Upload paper-signed EOI" button used to live here.
                It's now on the dedicated EOI tab (in both the active-EOI
                hero and the empty-state CTA row), where it sits next to
                the document it relates to. The header was a shotgun of
                actions that didn't all belong; collecting them per-tab
                is the cleaner UX. */}
            <PermissionGate resource="interests" action="edit">
              <button
                type="button"
                onClick={() => setEditOpen(true)}
                aria-label="Edit interest"
                title="Edit interest"
                className={cn(
                  'rounded-md p-1.5 text-muted-foreground/70 transition-colors',
                  'hover:bg-foreground/5 hover:text-foreground',
                )}
              >
                <Pencil className="size-4" aria-hidden />
              </button>
            </PermissionGate>
            <button
              type="button"
              onClick={() => setReminderOpen(true)}
              aria-label="Add reminder for this interest"
              title="Add reminder for this interest"
              className="rounded-md p-1.5 text-muted-foreground/70 transition-colors hover:bg-foreground/5 hover:text-primary"
            >
              <Bell className="size-4" aria-hidden />
            </button>
            <PermissionGate resource="interests" action="delete">
              <button
                type="button"
                onClick={() => setArchiveOpen(true)}
                aria-label={isArchived ? 'Restore interest' : 'Archive interest'}
                title={isArchived ? 'Restore interest' : 'Archive interest'}
                className={cn(
                  'rounded-md p-1.5 text-muted-foreground/70 transition-colors',
                  'hover:bg-foreground/5',
                  isArchived ? 'hover:text-foreground' : 'hover:text-destructive',
                )}
              >
                {isArchived ? (
                  <RotateCcw className="size-4" aria-hidden />
                ) : (
                  <Archive className="size-4" aria-hidden />
                )}
              </button>
            </PermissionGate>
          </div>
        </div>
      </DetailHeaderStrip>

      {outcomeDialog && (
        <InterestOutcomeDialog
          interestId={interest.id}
          mode={outcomeDialog}
          open={outcomeDialog !== null}
          onOpenChange={(open) => !open && setOutcomeDialog(null)}
        />
      )}

      <InterestForm
        open={editOpen}
        onOpenChange={setEditOpen}
        interest={interest as unknown as Parameters<typeof InterestForm>[0]['interest']}
      />

      <ReminderForm
        open={reminderOpen}
        onOpenChange={setReminderOpen}
        defaultInterestId={interest.id}
        defaultClientId={interest.clientId ?? undefined}
        onSuccess={() => queryClient.invalidateQueries({ queryKey: ['reminders'] })}
      />

      <ArchiveConfirmDialog
        open={archiveOpen}
        onOpenChange={setArchiveOpen}
        entityName={interest.clientName ?? 'Interest'}
        entityType="Interest"
        isArchived={isArchived}
        onConfirm={() => {
          if (isArchived) {
            restoreMutation.mutate();
          } else {
            archiveMutation.mutate();
          }
        }}
        isLoading={archiveMutation.isPending || restoreMutation.isPending}
      />

      <ContactLogComposeSheet
        interestId={interest.id}
        open={logContactOpen}
        onOpenChange={setLogContactOpen}
      />
    </>
  );
}
