import { useState } from "react";
import {
  Phone,
  Mail,
  User,
  Users,
  Calendar,
  Check,
  Copy,
  Link2,
  MoreVertical,
  Clock,
  ArrowRight,
  ChevronDown,
  ChevronRight,
  Sparkles,
  RefreshCw,
  Loader2,
  CheckCircle2,
  AlertCircle,
} from "lucide-react";
import { cn } from "@/lib/utils";
import { formatCurrency } from "@/lib/format-currency";
import { formatDateShort, daysUntil } from "@/lib/format-date";
import { Badge } from "@/components/ui/badge";
import { Button, buttonVariants } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";
import { TaskCheckItem } from "@/components/ui/pipeline-primitives";
import { Progress } from "@/components/ui/progress";
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip";

/**
 * OpportunityCard — WealthX DS (L3 Card)
 *
 * Kanban card for a single loan opportunity in the Pipeline board.
 * Renders customer info, loan metadata, task progress, and quick actions.
 *
 * This component is display-only — drag-and-drop is handled by the
 * KanbanColumn wrapper in the app.
 *
 * Data source: `listLoans()` → `Opportunity` in `loan-crm.ts`
 */

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

export type Priority = "HIGH" | "MEDIUM" | "LOW" | "NONE";

export interface OpportunityTask {
  id: string;
  title: string;
  completed: boolean;
}

export type CrmSyncStatus = "idle" | "syncing" | "synced" | "error";

/** A connected Broker CRM (e.g. Quicklii) this opportunity can sync/activate to. */
export interface CrmSyncTarget {
  id: string;
  name: string;
  status: CrmSyncStatus;
  /** ISO date string of the last successful sync, shown once `status` is `"synced"`. */
  lastSyncedAt?: string;
}

export interface OpportunityCardProps {
  // ── Core data ────────────────────────────────────────────────
  id: string;
  customerName: string;
  customerPhone?: string;
  customerEmail?: string;
  /** Number of additional co-applicants beyond the primary contact. */
  additionalContacts?: number;
  loanType?: string;
  loanPurposeLabel?: string;
  /** Loan amount in dollars. */
  amount: number;
  /** ISO date string of the opportunity creation date. */
  date: string;

  // ── Status ───────────────────────────────────────────────────
  priority: Priority;
  /** Days the opportunity has been in its current stage. */
  daysSinceColumnChanged?: number;
  /**
   * Stage threshold for MEDIUM (orange) warning color.
   * Comes from `Stage.warningDays`.
   */
  warningDays?: number;
  /**
   * Stage threshold for HIGH (red) priority color.
   * Comes from `Stage.priorityDays`.
   */
  priorityDays?: number;
  /** ISO date string — if set, the card shows an "On hold until …" banner. */
  onHoldTo?: string | null;
  /**
   * When `true`, the card renders in on-hold mode regardless of `onHoldTo`.
   * Timer/dot hidden, dropdown hides "Change priority"/"Put on hold", action
   * area shows "Place Back" only. Set by KanbanColumn for every card in the
   * on-hold column — no need to stamp `onHoldTo` just to activate the mode.
   */
  isOnHold?: boolean;
  /** Whether this opportunity represents a modification of a completed loan. */
  isModifyCompletedLoan?: boolean;

  // ── Tasks ────────────────────────────────────────────────────
  tasks?: OpportunityTask[];
  /** Title of the next pending task (shown as a hint below the task list). */
  nextTask?: string | null;

  // ── Lead data (passed through by KanbanColumn to LeadCard) ───
  /**
   * URL for the loan application form.
   * Not rendered by OpportunityCard — used by KanbanColumn to forward
   * to LeadCard when this opportunity is in the Leads stage.
   */
  loanApplicationUrl?: string;

  // ── Actions ──────────────────────────────────────────────────
  /** Fires when clicking the non-interactive card body (e.g. to open the summary drawer). */
  onCardClick?: () => void;
  onViewDetails?: () => void;
  onTaskToggle?: (taskId: string) => void;
  onMarkAsDone?: () => void;
  onMoveToNextStage?: () => void;
  onChangePriority?: () => void;
  onDelete?: () => void;
  onPutOnHold?: () => void;
  /**
   * Callback for the "Place Back" button — shown only when the card is in the
   * On Hold column. When provided, the card renders in on-hold column mode:
   * priority dot/timer are hidden, dropdown hides "Change priority" and "Put on hold",
   * and the action area shows "Place Back" instead of "Move to next stage"/"Mark as done".
   */
  onPlaceBack?: () => void;
  /**
   * Sends this opportunity's data to the AI Chrome extension.
   * Shown as a Sparkles icon button on the card header, visible on hover.
   */
  onSendToAI?: (opportunity: OpportunityCardProps) => void;

  /**
   * Connected Broker CRMs (e.g. Quicklii) this opportunity can sync/activate to.
   * Omit or leave empty to hide the sync button entirely.
   */
  crmSyncTargets?: CrmSyncTarget[];
  /** Fires when the broker activates or re-syncs a specific CRM target. */
  onSyncCrmTarget?: (targetId: string) => void;

  /** Shows a loading state on action buttons while an async op is in flight. */
  isSubmitting?: boolean;
  /** Whether the card is draggable (HTML5 native DnD). */
  draggable?: boolean;
  onDragStart?: React.DragEventHandler<HTMLDivElement>;
  className?: string;
  /**
   * Render mode for the card:
   * - `"deal"` (default) — full opportunity info with task accordion.
   * - `"task"` — compact task-first layout (next task, progress, deal ref).
   */
  viewMode?: "deal" | "task";
}

// ---------------------------------------------------------------------------
// Internal helpers
// ---------------------------------------------------------------------------

/** Used for the priority dot background — full-saturation token is fine on colored bg. */
const PRIORITY_COLORS: Record<Priority, string> = {
  HIGH: "var(--color-destructive)",
  MEDIUM: "var(--color-warning)",
  LOW: "var(--color-success)",
  NONE: "var(--color-muted-foreground)",
};

/** Used for text / icons on white/light backgrounds — darkened tokens ensure 4.5:1 contrast. */
const PRIORITY_TEXT_COLORS: Record<Priority, string> = {
  HIGH: "var(--color-destructive-text)",
  MEDIUM: "var(--color-warning-text)",
  LOW: "var(--color-success-text)",
  NONE: "var(--color-muted-foreground)",
};

function resolvePriority(
  days: number | undefined,
  warningDays: number | undefined,
  priorityDays: number | undefined,
  priority: Priority,
): Priority {
  if (days === undefined) return priority;
  if (priorityDays !== undefined && days >= priorityDays) return "HIGH";
  if (warningDays !== undefined && days >= warningDays) return "MEDIUM";
  if (warningDays !== undefined || priorityDays !== undefined) return "LOW";
  return priority;
}

function formatLoanType(type: string): string {
  return type
    .split("-")
    .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
    .join(" ");
}

/** Quick Loan applications label the purpose with a full timestamp, which is
 * far longer than a normal purpose label — cap it so it always fits the
 * header badge alongside the action icons. */
const LOAN_PURPOSE_LABEL_MAX_LENGTH = 17;

function truncateLoanPurposeLabel(label: string): string {
  return label.length > LOAN_PURPOSE_LABEL_MAX_LENGTH
    ? `${label.slice(0, LOAN_PURPOSE_LABEL_MAX_LENGTH)}…`
    : label;
}

// ---------------------------------------------------------------------------
// SendToAIButton — shared Sparkles button with tooltip
// ---------------------------------------------------------------------------

function SendToAIButton({ onClick }: { onClick: () => void }) {
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger
          render={
            <button
              type="button"
              className={cn(
                buttonVariants({ variant: "ghost", size: "icon" }),
                "size-7 shrink-0 text-muted-foreground",
              )}
              onClick={onClick}
              aria-label="Send to AI assistant"
            >
              <Sparkles className="size-3.5" />
            </button>
          }
        />
        <TooltipContent>Send to AI assistant</TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
}

// ---------------------------------------------------------------------------
// CrmSyncButton — activate/re-sync this opportunity's plan to connected
// Broker CRMs (e.g. Quicklii). Lists every target so the design scales past
// a single connected CRM without changing the trigger.
// ---------------------------------------------------------------------------

const CRM_STATUS_ICON: Record<CrmSyncStatus, React.ReactNode> = {
  idle: null,
  syncing: (
    <Loader2 className="size-3.5 shrink-0 animate-spin text-muted-foreground" />
  ),
  synced: (
    <CheckCircle2
      className="size-3.5 shrink-0"
      style={{ color: "var(--color-success-text)" }}
    />
  ),
  error: (
    <AlertCircle
      className="size-3.5 shrink-0"
      style={{ color: "var(--color-destructive-text)" }}
    />
  ),
};

function crmTargetActionLabel(status: CrmSyncStatus): string {
  if (status === "synced") return "Sync Again";
  if (status === "error") return "Retry";
  if (status === "syncing") return "Syncing…";
  return "First Sync";
}

type CrmAggregateStatus = CrmSyncStatus | "partial";

/**
 * Worst-case status across all targets, drives the trigger's aggregate dot.
 * "partial" (distinct from "idle") flags "some targets synced, some not" so
 * it doesn't read the same as "nothing synced yet".
 */
function crmAggregateStatus(targets: CrmSyncTarget[]): CrmAggregateStatus {
  if (targets.some((t) => t.status === "error")) return "error";
  if (targets.some((t) => t.status === "syncing")) return "syncing";
  if (targets.every((t) => t.status === "synced")) return "synced";
  if (targets.some((t) => t.status === "synced")) return "partial";
  return "idle";
}

const CRM_AGGREGATE_DOT_COLOR: Record<CrmAggregateStatus, string | undefined> =
  {
    idle: undefined,
    partial: "var(--color-muted-foreground)",
    syncing: "var(--color-warning)",
    synced: "var(--color-success)",
    error: "var(--color-destructive)",
  };

function CrmSyncButton({
  targets,
  onSync,
}: {
  targets: CrmSyncTarget[];
  onSync?: (targetId: string) => void;
}) {
  const aggregate = crmAggregateStatus(targets);
  const dotColor = CRM_AGGREGATE_DOT_COLOR[aggregate];

  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger render={<span className="inline-flex" />}>
          <DropdownMenu>
            <DropdownMenuTrigger
              className={cn(
                buttonVariants({ variant: "ghost", size: "icon" }),
                "relative size-7 shrink-0 text-muted-foreground",
              )}
              aria-label="Sync to CRM"
            >
              <RefreshCw className="size-3.5" />
              {dotColor && (
                <span
                  className="absolute right-0.5 top-0.5 size-1.5 rounded-full"
                  style={{ backgroundColor: dotColor }}
                  aria-hidden="true"
                />
              )}
            </DropdownMenuTrigger>
            <DropdownMenuContent>
              {targets.map((target) => (
                <DropdownMenuItem
                  key={target.id}
                  disabled={target.status === "syncing"}
                  onClick={() => onSync?.(target.id)}
                >
                  <span className="flex flex-1 items-center justify-between gap-3">
                    <span className="truncate">{target.name}</span>
                    <span className="flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground">
                      {CRM_STATUS_ICON[target.status]}
                      {crmTargetActionLabel(target.status)}
                    </span>
                  </span>
                </DropdownMenuItem>
              ))}
            </DropdownMenuContent>
          </DropdownMenu>
        </TooltipTrigger>
        <TooltipContent>Sync to CRM</TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
}

// ---------------------------------------------------------------------------
// TaskViewCard — compact task-first card (viewMode === "task")
//
// Three states driven by task progress:
//   A) Has next task   → shows task title + AI agent + segmented progress
//   B) All tasks done  → shows ✓ message + full green progress bar
//   C) No tasks        → shows fallback muted text
// ---------------------------------------------------------------------------

function TaskViewCard({
  id,
  customerName,
  customerPhone,
  customerEmail,
  additionalContacts,
  loanType,
  loanPurposeLabel,
  amount,
  date,
  priority,
  daysSinceColumnChanged,
  warningDays,
  priorityDays,
  onHoldTo,
  isOnHold,
  isModifyCompletedLoan,
  tasks = [],
  nextTask,
  onCardClick,
  onViewDetails,
  onTaskToggle,
  onMarkAsDone,
  onMoveToNextStage,
  onChangePriority,
  onDelete,
  onPutOnHold,
  onPlaceBack,
  onSendToAI,
  crmSyncTargets,
  onSyncCrmTarget,
  isSubmitting = false,
  draggable = false,
  onDragStart,
  className,
}: OpportunityCardProps): React.JSX.Element {
  const resolvedPriority = resolvePriority(
    daysSinceColumnChanged,
    warningDays,
    priorityDays,
    priority,
  );
  const priorityColor = PRIORITY_COLORS[resolvedPriority];

  const completedCount = tasks.filter((t) => t.completed).length;
  const totalCount = tasks.length;
  const hasTasks = totalCount > 0;
  const allDone = hasTasks && completedCount === totalCount;
  const isOnHoldCard = isOnHold ?? Boolean(onHoldTo);

  const [subtasksExpanded, setSubtasksExpanded] = useState(false);

  const hasMenu = !!(
    onViewDetails ||
    onDelete ||
    (!isOnHoldCard && (onChangePriority || onPutOnHold))
  );
  const stopProp = (e: React.MouseEvent): void => {
    e.stopPropagation();
  };

  // Compact deal reference: "John Smith · Buy a House · $850,000"
  const purposeLabel =
    loanPurposeLabel ?? (loanType ? formatLoanType(loanType) : null);
  const dealRef = [
    customerName,
    purposeLabel,
    amount > 0 ? formatCurrency(amount) : null,
  ]
    .filter(Boolean)
    .join(" · ");

  // Task header content (no nested ternary — avoids lint error)
  let taskHeader: React.ReactNode;
  if (allDone) {
    taskHeader = (
      <p
        className="flex items-center gap-1.5 text-sm font-semibold"
        style={{ color: "var(--color-success-text)" }}
      >
        <Check className="size-3.5 shrink-0" />
        All tasks complete
      </p>
    );
  } else if (nextTask) {
    taskHeader = (
      <p className="truncate text-sm font-semibold leading-snug">{nextTask}</p>
    );
  } else {
    taskHeader = (
      <p className="text-xs text-muted-foreground">
        No tasks defined for this stage
      </p>
    );
  }

  return (
    <div
      className={cn(
        "group flex flex-col gap-2.5 border border-border bg-background p-3 text-foreground shadow-sm",
        onCardClick && "cursor-pointer",
        draggable && "cursor-grab active:cursor-grabbing",
        isSubmitting && "opacity-60",
        className,
      )}
      data-slot="opportunity-card"
      draggable={draggable}
      onDragStart={onDragStart}
      onClick={onCardClick}
    >
      {/* ── Task header + priority dot ── */}
      <div className="flex items-start gap-2">
        <div className="min-w-0 flex-1">{taskHeader}</div>
        <span
          role="img"
          className="mt-0.5 inline-block size-2.5 shrink-0 rounded-full"
          style={{ backgroundColor: priorityColor }}
          aria-label={`Priority: ${resolvedPriority}`}
        />
      </div>

      {/* ── Progress (only when tasks exist) ── */}
      {hasTasks && (
        <div className="flex items-center gap-2">
          <span className="shrink-0 tabular-nums text-xs text-muted-foreground">
            {completedCount}/{totalCount}
          </span>
          <Progress
            value={(completedCount / totalCount) * 100}
            className={cn(
              "h-1.5 flex-1",
              allDone && "[&_[data-slot=progress-indicator]]:bg-success",
            )}
          />
        </div>
      )}

      {/* ── Collapsible subtask list ── */}
      {hasTasks && (
        <div
          className="space-y-1 border-t border-border pt-2"
          onClick={stopProp}
          role="presentation"
          onKeyDown={(e) => e.stopPropagation()}
        >
          <button
            type="button"
            onClick={() => setSubtasksExpanded((v) => !v)}
            className="flex w-full items-center justify-between text-xs text-muted-foreground hover:text-foreground"
          >
            <span className="flex items-center gap-1">
              {subtasksExpanded ? (
                <ChevronDown className="size-3" />
              ) : (
                <ChevronRight className="size-3" />
              )}
              Subtasks
            </span>
            <span>
              {completedCount} / {totalCount}
            </span>
          </button>
          {subtasksExpanded && (
            <ul className="space-y-1.5 pt-1">
              {tasks.map((task) => (
                <TaskCheckItem
                  key={task.id}
                  title={task.title}
                  completed={task.completed}
                  onToggle={() => onTaskToggle?.(task.id)}
                  size="xs"
                />
              ))}
            </ul>
          )}
        </div>
      )}

      {/* ── Deal reference line ── */}
      <p className="truncate text-xs text-muted-foreground">{dealRef}</p>

      {/* ── Footer: days badge + AI button + 3-dot menu ── */}
      <div className="flex items-center gap-1.5" onClick={stopProp}>
        {daysSinceColumnChanged !== undefined && (
          <Badge variant="secondary" className="px-1.5 text-[10px] font-normal">
            {daysSinceColumnChanged}d
          </Badge>
        )}
        <div className="ml-auto flex items-center gap-0.5">
          {onSendToAI && (
            <SendToAIButton
              onClick={() =>
                onSendToAI({
                  id,
                  customerName,
                  customerPhone,
                  customerEmail,
                  additionalContacts,
                  loanType,
                  loanPurposeLabel,
                  amount,
                  date,
                  priority,
                  daysSinceColumnChanged,
                  warningDays,
                  priorityDays,
                  onHoldTo,
                  isOnHold,
                  isModifyCompletedLoan,
                  tasks,
                  nextTask,
                })
              }
            />
          )}
          {crmSyncTargets && crmSyncTargets.length > 0 && (
            <CrmSyncButton targets={crmSyncTargets} onSync={onSyncCrmTarget} />
          )}
          {hasMenu && (
            <DropdownMenu>
              <DropdownMenuTrigger
                className={cn(
                  buttonVariants({ variant: "ghost", size: "icon" }),
                  "size-7 shrink-0",
                )}
                aria-label="Opportunity actions"
              >
                <MoreVertical className="size-4" />
              </DropdownMenuTrigger>
              <DropdownMenuContent align="end">
                {onViewDetails && (
                  <DropdownMenuItem onClick={onViewDetails}>
                    View details
                  </DropdownMenuItem>
                )}
                {!isOnHoldCard && onChangePriority && (
                  <DropdownMenuItem onClick={onChangePriority}>
                    Change priority
                  </DropdownMenuItem>
                )}
                {!isOnHoldCard && onPutOnHold && (
                  <DropdownMenuItem onClick={onPutOnHold}>
                    Put on hold
                  </DropdownMenuItem>
                )}
                {onDelete && (
                  <>
                    <DropdownMenuSeparator />
                    <DropdownMenuItem onClick={onDelete} variant="destructive">
                      Delete
                    </DropdownMenuItem>
                  </>
                )}
              </DropdownMenuContent>
            </DropdownMenu>
          )}
        </div>
      </div>

      {/* ── Action button ── */}
      {isOnHoldCard && onPlaceBack && (
        <div onClick={stopProp}>
          <Separator />
          <div className="pt-2">
            <Button
              variant="outline"
              size="sm"
              className="w-full text-caption"
              onClick={onPlaceBack}
              disabled={isSubmitting}
            >
              Place Back
            </Button>
          </div>
        </div>
      )}
      {!onHoldTo && allDone && onMoveToNextStage && (
        <div onClick={stopProp}>
          <Separator />
          <div className="pt-2">
            <Button
              variant="outline"
              size="sm"
              className="w-full text-caption"
              onClick={onMoveToNextStage}
              disabled={isSubmitting}
            >
              Move to next stage
            </Button>
          </div>
        </div>
      )}
      {!onHoldTo && !allDone && nextTask && onMarkAsDone && (
        <div onClick={stopProp}>
          <Separator />
          <div className="pt-2">
            <Button
              variant="default"
              size="sm"
              className="w-full text-caption"
              onClick={onMarkAsDone}
              disabled={isSubmitting}
            >
              Mark as done
            </Button>
          </div>
        </div>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// OpportunityCard
// ---------------------------------------------------------------------------

export function OpportunityCard({
  id,
  customerName,
  customerPhone,
  customerEmail,
  additionalContacts,
  loanType,
  loanPurposeLabel,
  amount,
  date,
  priority,
  daysSinceColumnChanged,
  warningDays,
  priorityDays,
  onHoldTo,
  isOnHold,
  isModifyCompletedLoan,
  tasks = [],
  nextTask,
  onCardClick,
  onViewDetails,
  onTaskToggle,
  onMarkAsDone,
  onMoveToNextStage,
  onChangePriority,
  onDelete,
  onPutOnHold,
  onPlaceBack,
  onSendToAI,
  crmSyncTargets,
  onSyncCrmTarget,
  isSubmitting = false,
  draggable = false,
  onDragStart,
  className,
  viewMode = "deal",
}: OpportunityCardProps) {
  const isOnHoldCard = isOnHold ?? Boolean(onHoldTo);

  if (viewMode === "task") {
    return (
      <TaskViewCard
        id={id}
        customerName={customerName}
        customerPhone={customerPhone}
        customerEmail={customerEmail}
        additionalContacts={additionalContacts}
        loanType={loanType}
        loanPurposeLabel={loanPurposeLabel}
        amount={amount}
        date={date}
        priority={priority}
        daysSinceColumnChanged={daysSinceColumnChanged}
        warningDays={warningDays}
        priorityDays={priorityDays}
        onHoldTo={onHoldTo}
        isOnHold={isOnHoldCard}
        isModifyCompletedLoan={isModifyCompletedLoan}
        tasks={tasks}
        nextTask={nextTask}
        onCardClick={onCardClick}
        onViewDetails={onViewDetails}
        onTaskToggle={onTaskToggle}
        onMarkAsDone={onMarkAsDone}
        onMoveToNextStage={onMoveToNextStage}
        onChangePriority={onChangePriority}
        onDelete={onDelete}
        onPutOnHold={onPutOnHold}
        onPlaceBack={onPlaceBack}
        onSendToAI={onSendToAI}
        crmSyncTargets={crmSyncTargets}
        onSyncCrmTarget={onSyncCrmTarget}
        isSubmitting={isSubmitting}
        draggable={draggable}
        onDragStart={onDragStart}
        className={className}
      />
    );
  }

  const resolvedPriority = resolvePriority(
    daysSinceColumnChanged,
    warningDays,
    priorityDays,
    priority,
  );
  const priorityColor = PRIORITY_COLORS[resolvedPriority];
  const priorityTextColor = PRIORITY_TEXT_COLORS[resolvedPriority];

  const completedCount = tasks.filter((t) => t.completed).length;
  const hasTasks = tasks.length > 0;
  const hasActions = !!(isOnHoldCard
    ? onPlaceBack
    : onMarkAsDone || onMoveToNextStage);
  const hasMenu = !!(
    onViewDetails ||
    onDelete ||
    (!isOnHoldCard && (onChangePriority || onPutOnHold))
  );

  const stopProp = (e: React.MouseEvent): void => {
    e.stopPropagation();
  };

  return (
    <div
      className={cn(
        "group flex flex-col gap-2 border border-border bg-background p-4 text-foreground shadow-sm",
        onCardClick && "cursor-pointer",
        draggable && "cursor-grab active:cursor-grabbing",
        isSubmitting && "opacity-60",
        className,
      )}
      data-slot="opportunity-card"
      draggable={draggable}
      onDragStart={onDragStart}
      onClick={onCardClick}
    >
      {/* ── On-hold banner ── */}
      {onHoldTo && (
        <div
          className="flex items-center gap-1.5 rounded border border-warning/30 bg-warning/10 px-2 py-1 text-xs font-medium"
          style={{ color: "var(--color-warning-text)" }}
        >
          <Clock className="size-3 shrink-0" />
          On hold until {formatDateShort(onHoldTo)}
          {daysUntil(onHoldTo) > 0 ? ` (${daysUntil(onHoldTo)}d left)` : ""}
        </div>
      )}

      {/* ── Modify-completed-loan tag ── */}
      {isModifyCompletedLoan && (
        <div
          className="flex items-center gap-1.5 rounded border border-info/30 bg-info/10 px-2 py-1 text-xs font-medium"
          style={{ color: "var(--color-info-text)" }}
        >
          Modify completed loan
        </div>
      )}

      {/* ── Header: loan purpose + amount + menu ── */}
      <div className="flex items-start justify-between gap-2">
        <div className="flex min-w-0 flex-1 flex-col gap-1">
          {(loanPurposeLabel || loanType) && (
            <Badge variant="outline" className="max-w-full truncate self-start">
              {truncateLoanPurposeLabel(
                loanPurposeLabel ?? formatLoanType(loanType!),
              )}
            </Badge>
          )}
          <span className="text-base font-bold tabular-nums text-foreground">
            {formatCurrency(amount)}
          </span>
        </div>

        <div className="flex items-center gap-1 -mr-1 -mt-1" onClick={stopProp}>
          {onSendToAI && (
            <SendToAIButton
              onClick={() =>
                onSendToAI({
                  id,
                  customerName,
                  customerPhone,
                  customerEmail,
                  additionalContacts,
                  loanType,
                  loanPurposeLabel,
                  amount,
                  date,
                  priority,
                  daysSinceColumnChanged,
                  warningDays,
                  priorityDays,
                  onHoldTo,
                  isOnHold,
                  isModifyCompletedLoan,
                  tasks,
                  nextTask,
                })
              }
            />
          )}
          {crmSyncTargets && crmSyncTargets.length > 0 && (
            <CrmSyncButton targets={crmSyncTargets} onSync={onSyncCrmTarget} />
          )}
          {hasMenu && (
            <DropdownMenu>
              <DropdownMenuTrigger
                className={cn(
                  buttonVariants({ variant: "ghost", size: "icon" }),
                  "size-7 shrink-0",
                )}
                aria-label="Opportunity actions"
              >
                <MoreVertical className="size-4" />
              </DropdownMenuTrigger>
              <DropdownMenuContent align="end">
                {onViewDetails && (
                  <DropdownMenuItem onClick={onViewDetails}>
                    View details
                  </DropdownMenuItem>
                )}
                {!isOnHoldCard && onChangePriority && (
                  <DropdownMenuItem onClick={onChangePriority}>
                    Change priority
                  </DropdownMenuItem>
                )}
                {!isOnHoldCard && onPutOnHold && (
                  <DropdownMenuItem onClick={onPutOnHold}>
                    Put on hold
                  </DropdownMenuItem>
                )}
                {onDelete && (
                  <>
                    <DropdownMenuSeparator />
                    <DropdownMenuItem onClick={onDelete} variant="destructive">
                      Delete
                    </DropdownMenuItem>
                  </>
                )}
              </DropdownMenuContent>
            </DropdownMenu>
          )}
        </div>
      </div>

      <Separator />

      {/* ── Customer info ── */}
      <div className="flex flex-col gap-1">
        <div className="flex items-center justify-between gap-2">
          <span className="truncate text-sm font-semibold text-foreground">
            {customerName}
          </span>
          {additionalContacts && additionalContacts > 0 ? (
            <Badge variant="secondary" className="shrink-0 gap-1">
              <Users className="size-3" aria-hidden="true" />
              Joint
            </Badge>
          ) : (
            <Badge variant="secondary" className="shrink-0 gap-1">
              <User className="size-3" aria-hidden="true" />
              Individual
            </Badge>
          )}
        </div>
        {customerPhone && (
          <span className="flex items-center gap-1.5 text-xs text-muted-foreground">
            <Phone className="size-3 shrink-0" aria-hidden="true" />
            {customerPhone}
          </span>
        )}
        {customerEmail && (
          <span className="flex items-center gap-1.5 text-xs text-muted-foreground">
            <Mail className="size-3 shrink-0" aria-hidden="true" />
            <span className="truncate">{customerEmail}</span>
          </span>
        )}
      </div>

      <Separator />

      {/* ── Metadata: date (left) | days-since chip + priority dot (right, adjacent) ── */}
      <div className="flex items-center justify-between">
        <span className="flex items-center gap-1.5 text-xs text-muted-foreground">
          <Calendar className="size-3 shrink-0" aria-hidden="true" />
          {formatDateShort(date)}
        </span>

        <span className="flex items-center gap-1.5">
          {!isOnHoldCard && daysSinceColumnChanged !== undefined && (
            <>
              <Clock
                className="size-3 shrink-0"
                style={{ color: priorityTextColor }}
                aria-hidden="true"
              />
              <span
                className="text-xs font-medium tabular-nums"
                style={{ color: priorityTextColor }}
              >
                {daysSinceColumnChanged}d
              </span>
            </>
          )}
          {/* Dot: hidden when card is on hold */}
          {!isOnHoldCard && (
            <span
              role="img"
              className="inline-block size-2 shrink-0 rounded-full"
              style={{ backgroundColor: priorityColor }}
              aria-label={`Priority: ${resolvedPriority}`}
            />
          )}
        </span>
      </div>

      {/* ── Tasks: segmented progress bar + animated accordion ── */}
      {hasTasks && (
        // stopPropagation: accordion expand/collapse + task checkboxes must not bubble to onCardClick
        <div onClick={stopProp}>
          {/* Segmented bar — one segment per task, filled = completed */}
          <div
            className="flex gap-0.5"
            role="progressbar"
            aria-valuenow={completedCount}
            aria-valuemin={0}
            aria-valuemax={tasks.length}
            aria-label={`${completedCount} of ${tasks.length} tasks complete`}
          >
            {tasks.map((t, i) => (
              <div
                key={t.id}
                className={cn(
                  "h-[7px] flex-1",
                  i < completedCount ? "bg-primary" : "bg-muted",
                )}
              />
            ))}
          </div>

          {/* Accordion — animated expand/collapse using shadcn Accordion */}
          <Accordion className="-mx-4">
            <AccordionItem value="tasks" className="border-0">
              <AccordionTrigger className="px-4 py-1.5 text-xs font-normal text-muted-foreground hover:no-underline hover:text-foreground [&>svg]:size-3.5">
                Tasks ({completedCount}/{tasks.length})
              </AccordionTrigger>
              <AccordionContent className="px-4">
                <div className="flex flex-col">
                  {tasks.map((task) => (
                    <TaskCheckItem
                      key={task.id}
                      title={task.title}
                      completed={task.completed}
                      onToggle={
                        onTaskToggle ? () => onTaskToggle(task.id) : undefined
                      }
                      disabled={isSubmitting}
                    />
                  ))}
                </div>
              </AccordionContent>
            </AccordionItem>
          </Accordion>

          {/* Next task hint — only visible when accordion is collapsed */}
          {nextTask && (
            <div className="flex items-start gap-1.5 border border-primary/30 bg-primary/5 px-2 py-1.5 text-xs">
              <ArrowRight
                className="mt-0.5 size-3 shrink-0 text-primary"
                aria-hidden="true"
              />
              <span className="font-medium">Next:</span>
              <span className="text-muted-foreground">{nextTask}</span>
            </div>
          )}
        </div>
      )}

      {/* ── Action buttons ── */}
      {hasActions && (
        // stopPropagation: button clicks must not bubble to onCardClick
        <div onClick={stopProp}>
          <Separator />
          <div className="flex gap-2 pt-2">
            {isOnHoldCard ? (
              <Button
                variant="outline"
                size="sm"
                className="flex-1 text-caption"
                onClick={onPlaceBack}
                disabled={isSubmitting}
              >
                Place Back
              </Button>
            ) : (
              <>
                {onMoveToNextStage && (
                  <Button
                    variant="outline"
                    size="sm"
                    className="flex-1 text-caption"
                    onClick={onMoveToNextStage}
                    disabled={isSubmitting}
                  >
                    Move to next stage
                  </Button>
                )}
                {onMarkAsDone && (
                  <Button
                    variant="default"
                    size="sm"
                    className="flex-1 text-caption"
                    onClick={onMarkAsDone}
                    disabled={isSubmitting}
                  >
                    Mark as done
                  </Button>
                )}
              </>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// LeadCard — simplified card for the Leads stage
//
// Leads are new clients who haven't started their loan application yet.
// No loan amount, no purpose tag, no joint badge, no tasks, no date.
// Primary action: send them the loan application link.
// ---------------------------------------------------------------------------

function normalizeUrl(url: string): string {
  return `https://${url.replace(/^https?:\/\//, "")}`;
}

/** Shortened + copyable loan application URL row. */
function LoanApplicationLink({ url }: { url: string }) {
  const [copied, setCopied] = useState(false);
  const href = normalizeUrl(url);

  function handleCopy() {
    navigator.clipboard.writeText(href).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    });
  }

  return (
    <div className="flex flex-col gap-1">
      <p className="text-caption text-muted-foreground">
        Or the link below to fill out the loan application directly.
      </p>
      <div className="flex items-center gap-1.5">
        <Link2 className="size-4 shrink-0 text-muted-foreground" />
        <a
          href={href}
          target="_blank"
          rel="noreferrer"
          className="min-w-0 flex-1 truncate text-body-small text-primary underline-offset-2 hover:underline"
        >
          {url}
        </a>
        <button
          type="button"
          onClick={handleCopy}
          className="shrink-0 rounded p-1 text-muted-foreground transition-colors hover:text-foreground"
          aria-label="Copy link"
        >
          {copied ? (
            <Check className="size-4 text-success-text" />
          ) : (
            <Copy className="size-4" />
          )}
        </button>
      </div>
    </div>
  );
}

export interface LeadCardProps {
  id: string;
  customerName: string;
  customerPhone?: string;
  customerEmail?: string;
  onSendLoanApplication?: () => void;
  loanApplicationUrl?: string;
  onDelete?: () => void;
  onSendToAI?: () => void;
  isSubmitting?: boolean;
  className?: string;
}

export function LeadCard({
  customerName,
  customerPhone,
  customerEmail,
  onSendLoanApplication,
  loanApplicationUrl,
  onDelete,
  onSendToAI,
  isSubmitting = false,
  className,
}: LeadCardProps) {
  return (
    <div
      className={cn(
        "flex flex-col gap-3 border border-border bg-background p-4 text-foreground shadow-sm",
        isSubmitting && "opacity-60",
        className,
      )}
      data-slot="lead-card"
    >
      {/* ── Customer info + delete menu ── */}
      <div className="flex items-start justify-between gap-2">
        <div className="flex min-w-0 flex-1 flex-col gap-1">
          <span className="text-label-medium text-foreground">
            {customerName}
          </span>
          {customerPhone && (
            <span className="flex items-center gap-1.5 text-caption text-muted-foreground">
              <Phone className="size-3.5 shrink-0" aria-hidden="true" />
              {customerPhone}
            </span>
          )}
          {customerEmail && (
            <span className="flex items-center gap-1.5 text-caption text-muted-foreground">
              <Mail className="size-3.5 shrink-0" aria-hidden="true" />
              <span className="truncate">{customerEmail}</span>
            </span>
          )}
        </div>

        <div className="flex items-center gap-0.5 -mr-1 -mt-1">
          {onSendToAI && <SendToAIButton onClick={onSendToAI} />}
          {onDelete && (
            <DropdownMenu>
              <DropdownMenuTrigger
                className={cn(
                  buttonVariants({ variant: "ghost", size: "icon" }),
                  "size-7 shrink-0",
                )}
                aria-label="Lead actions"
              >
                <MoreVertical className="size-4" />
              </DropdownMenuTrigger>
              <DropdownMenuContent align="end">
                <DropdownMenuItem
                  onClick={onDelete}
                  className="text-destructive focus:text-destructive"
                >
                  Delete
                </DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
          )}
        </div>
      </div>

      <Separator />

      {/* ── Send loan application action ── */}
      {onSendLoanApplication && (
        <div className="flex flex-col gap-2">
          <Button
            variant="outline"
            size="sm"
            className="w-full text-caption"
            onClick={onSendLoanApplication}
            disabled={isSubmitting}
          >
            Send Loan Application Request
          </Button>
          {loanApplicationUrl && (
            <LoanApplicationLink url={loanApplicationUrl} />
          )}
        </div>
      )}
    </div>
  );
}
