'use client';

import { useState } from 'react';
import Link from 'next/link';
import { useParams } from 'next/navigation';
import type { Route } from 'next';
import { useQuery } from '@tanstack/react-query';
import { format, formatDistanceToNowStrict } from 'date-fns';
import { ArrowRight, CheckCircle2, ChevronRight, Circle, Plus } from 'lucide-react';

import { Button } from '@/components/ui/button';
import { EmptyState } from '@/components/shared/empty-state';
import { Skeleton } from '@/components/ui/skeleton';
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';
import { apiFetch } from '@/lib/api/client';
import { PIPELINE_STAGES, type PipelineStage } from '@/lib/constants';
import { deriveInterestBerthLabel } from '@/lib/templates/interest-berth-label';
import { cn } from '@/lib/utils';

import { STAGE_BADGE, STAGE_LABELS, safeStage } from '@/components/clients/pipeline-constants';
import {
  StageStepper,
  useClientInterests,
  type ClientInterestRow,
} from '@/components/clients/client-pipeline-summary';
import { InterestForm } from '@/components/interests/interest-form';
import { TagBadge } from '@/components/shared/tag-badge';

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

function InterestRowItem({
  interest,
  onOpen,
}: {
  interest: ClientInterestRow;
  onOpen: (i: ClientInterestRow) => void;
}) {
  const stage = safeStage(interest.pipelineStage);

  const berthDisplay =
    deriveInterestBerthLabel(interest.berthMoorings) ?? interest.berthMooringNumber;
  const berthLabel = berthDisplay ? `Berth ${berthDisplay}` : 'General interest';

  const yachtLabel = interest.yachtName ?? null;

  return (
    // Tap opens a right-side Sheet preview rather than navigating to the
    // full interest page. The sheet covers ~80% of interactions ("what
    // stage is this at, when did we last touch it"). For deeper edits
    // the sheet has an "Open full page" CTA.
    <button
      type="button"
      onClick={() => onOpen(interest)}
      className={cn(
        'group block w-full rounded-xl border border-border bg-card p-4 text-left shadow-sm transition-all',
        'hover:border-border/70 hover:shadow-md',
      )}
    >
      <div className="flex items-start justify-between gap-3">
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-2 flex-wrap">
            <h3 className="truncate text-base font-semibold tracking-tight text-foreground">
              {berthLabel}
            </h3>
            <span
              className={cn(
                'shrink-0 rounded-full px-2 py-0.5 text-xs font-medium',
                STAGE_BADGE[stage],
              )}
            >
              {STAGE_LABELS[stage]}
            </span>
          </div>
          {yachtLabel ? (
            <p className="mt-0.5 truncate text-xs text-muted-foreground">{yachtLabel}</p>
          ) : null}
        </div>
        <ChevronRight
          className="size-4 shrink-0 text-muted-foreground transition-transform group-hover:translate-x-0.5"
          aria-hidden
        />
      </div>

      <div className="mt-3">
        <StageStepper current={stage} />
      </div>
      {interest.tags && interest.tags.length > 0 ? (
        <div className="mt-2 flex flex-wrap gap-1">
          {interest.tags.slice(0, 4).map((t) => (
            <TagBadge key={t.id} name={t.name} color={t.color} />
          ))}
          {interest.tags.length > 4 ? (
            <span className="text-xs text-muted-foreground">+{interest.tags.length - 4} more</span>
          ) : null}
        </div>
      ) : null}
    </button>
  );
}

function lastActivityFor(interest: ClientInterestRow): string | null {
  const candidates = [interest.dateLastContact, interest.updatedAt]
    .filter((v): v is string => Boolean(v))
    .map((v) => new Date(v).getTime())
    .filter((t) => !Number.isNaN(t));
  if (candidates.length === 0) return null;
  return `${formatDistanceToNowStrict(new Date(Math.max(...candidates)))} ago`;
}

/** Full interest record returned by `/api/v1/interests/[id]`. Only the fields
 *  the preview sheet actually reads are typed here; the API returns more. */
interface InterestDetail {
  id: string;
  pipelineStage: string;
  leadCategory: string | null;
  source: string | null;
  notes: string | null;
  dateLastContact: string | null;
  dateEoiSent: string | null;
  dateEoiSigned: string | null;
  dateDepositReceived: string | null;
  dateContractSent: string | null;
  dateContractSigned: string | null;
  eoiDocStatus: string | null;
  reservationDocStatus: string | null;
  contractDocStatus: string | null;
  tags?: Array<{ id: string; name: string; color: string }>;
}

function useInterestDetail(id: string | null) {
  return useQuery<{ data: InterestDetail }>({
    queryKey: ['interest-detail-preview', id],
    queryFn: () => apiFetch<{ data: InterestDetail }>(`/api/v1/interests/${id}`),
    enabled: id !== null,
    // Detail rarely changes during a single drawer-open session; stale-time
    // keeps re-opens snappy without preventing background refetch.
    staleTime: 30_000,
  });
}

/** Format a date-only or ISO timestamp as e.g. "Apr 8, 2026". Returns null for
 *  empty input so callers can render an "empty" state. */
function formatDate(value: string | null | undefined): string | null {
  if (!value) return null;
  const d = new Date(value);
  if (Number.isNaN(d.getTime())) return null;
  return format(d, 'MMM d, yyyy');
}

/** A single milestone row inside the preview sheet's milestone summary. Filled
 *  circle when the step is done, hollow when pending. Trailing meta line
 *  shows the date stamp or a "pending" hint. */
function MilestoneRow({
  label,
  done,
  date,
  hint = 'pending',
}: {
  label: string;
  done: boolean;
  date: string | null;
  hint?: string;
}) {
  return (
    <li className="flex items-center gap-2 py-1">
      {done ? (
        <CheckCircle2 className="size-4 shrink-0 text-emerald-600" aria-hidden />
      ) : (
        <Circle className="size-4 shrink-0 text-muted-foreground/40" aria-hidden />
      )}
      <span className={cn('flex-1 text-sm', done ? 'text-foreground' : 'text-muted-foreground')}>
        {label}
      </span>
      <span className="text-xs text-muted-foreground tabular-nums">{date ?? hint}</span>
    </li>
  );
}

/**
 * Right-side sheet preview of a single interest. "Tap an interest → see
 * what's happening without leaving the client page". Shows the pipeline
 * progress, a compact milestone summary (EOI / Deposit / Contract),
 * lead context, last contact, and a notes teaser. Tap-out / Esc
 * dismisses; the full edit page is one tap away via "Open full page →".
 */
function InterestPreviewSheet({
  interest,
  portSlug,
  onClose,
}: {
  interest: ClientInterestRow | null;
  portSlug: string;
  onClose: () => void;
}) {
  // Pin the most recently selected interest so the sheet stays populated
  // during the close-animation tail (Radix keeps the content mounted
  // through the slide-out). Conditional setState is safe here - the
  // guard ensures it only fires when the prop actually changes.
  const [pinned, setPinned] = useState<ClientInterestRow | null>(interest);
  if (interest && interest !== pinned) setPinned(interest);
  const showing = pinned;

  const detail = useInterestDetail(showing?.id ?? null);
  const fullDetail = detail.data?.data ?? null;

  const open = interest !== null;
  const stage = showing ? safeStage(showing.pipelineStage) : null;
  const stageIdx = stage ? PIPELINE_STAGES.indexOf(stage) : -1;
  const reached = (target: PipelineStage) =>
    stageIdx !== -1 && PIPELINE_STAGES.indexOf(target) <= stageIdx;

  const showingBerthDisplay = showing
    ? (deriveInterestBerthLabel(showing.berthMoorings) ?? showing.berthMooringNumber)
    : null;
  const berthLabel = showing
    ? showingBerthDisplay
      ? `Berth ${showingBerthDisplay}`
      : 'General interest'
    : '';
  const yachtLabel = showing?.yachtName ?? null;
  const activity = showing ? lastActivityFor(showing) : null;
  const fullHref = showing ? (`/${portSlug}/interests/${showing.id}` as Route) : ('/' as Route);

  const leadLabel = fullDetail?.leadCategory
    ? (LEAD_CATEGORY_LABELS[fullDetail.leadCategory] ?? fullDetail.leadCategory)
    : null;
  const sourceLabel = fullDetail?.source
    ? fullDetail.source.replace(/\b\w/g, (m) => m.toUpperCase())
    : null;
  const lastContactDate = formatDate(fullDetail?.dateLastContact);
  const notesPreview = fullDetail?.notes?.trim() || null;

  return (
    <Sheet
      open={open}
      onOpenChange={(next) => {
        if (!next) onClose();
      }}
    >
      <SheetContent side="right" className="w-full overflow-y-auto sm:max-w-md">
        <SheetHeader>
          <div className="flex items-start justify-between gap-3 pr-8">
            <div className="min-w-0 flex-1">
              <SheetTitle className="truncate text-left">{berthLabel}</SheetTitle>
              {yachtLabel ? (
                <p className="mt-0.5 truncate text-sm text-muted-foreground">{yachtLabel}</p>
              ) : null}
            </div>
            {stage ? (
              <span
                className={cn(
                  'shrink-0 rounded-full px-2.5 py-1 text-xs font-medium',
                  STAGE_BADGE[stage],
                )}
              >
                {STAGE_LABELS[stage]}
              </span>
            ) : null}
          </div>
        </SheetHeader>

        <div className="mt-5 space-y-5">
          {/* Pipeline-stepper segmented bar - the same primitive used on the
              row card, so the at-a-glance progress hint is consistent
              across surfaces. */}
          {stage ? (
            <div>
              <p className="mb-1.5 text-xs font-medium uppercase tracking-wide text-muted-foreground">
                Pipeline progress
              </p>
              <StageStepper current={stage} />
              {detail.data?.data.tags && detail.data.data.tags.length > 0 ? (
                <div className="mt-2 flex flex-wrap gap-1">
                  {detail.data.data.tags.map((t) => (
                    <TagBadge key={t.id} name={t.name} color={t.color} />
                  ))}
                </div>
              ) : null}
            </div>
          ) : null}

          {/* Milestones - three sections matching the full interest detail
              page (EOI / Deposit / Contract). Done-state is derived from
              the pipeline stage so seed data without per-step dates still
              renders correctly. The full milestone columns + per-step
              actions live behind "Open full page". */}
          <section>
            <p className="mb-2 text-xs font-medium uppercase tracking-wide text-muted-foreground">
              Milestones
            </p>
            <div className="space-y-3">
              <div className="rounded-lg border border-border bg-card/50 p-3">
                <p className="mb-1 text-sm font-semibold">EOI</p>
                <ul>
                  <MilestoneRow
                    label="EOI sent"
                    done={reached('eoi') || !!fullDetail?.dateEoiSent}
                    date={formatDate(fullDetail?.dateEoiSent)}
                  />
                  <MilestoneRow
                    label="EOI signed"
                    done={
                      fullDetail?.eoiDocStatus === 'signed' ||
                      stageIdx > PIPELINE_STAGES.indexOf('eoi') ||
                      !!fullDetail?.dateEoiSigned
                    }
                    date={formatDate(fullDetail?.dateEoiSigned)}
                  />
                </ul>
              </div>
              <div className="rounded-lg border border-border bg-card/50 p-3">
                <p className="mb-1 text-sm font-semibold">Deposit</p>
                <ul>
                  <MilestoneRow
                    label="Deposit received"
                    done={reached('deposit_paid') || !!fullDetail?.dateDepositReceived}
                    date={formatDate(fullDetail?.dateDepositReceived)}
                  />
                </ul>
              </div>
              <div className="rounded-lg border border-border bg-card/50 p-3">
                <p className="mb-1 text-sm font-semibold">Contract</p>
                <ul>
                  <MilestoneRow
                    label="Contract sent"
                    done={reached('contract') || !!fullDetail?.dateContractSent}
                    date={formatDate(fullDetail?.dateContractSent)}
                  />
                  <MilestoneRow
                    label="Contract signed"
                    done={
                      fullDetail?.contractDocStatus === 'signed' || !!fullDetail?.dateContractSigned
                    }
                    date={formatDate(fullDetail?.dateContractSigned)}
                  />
                </ul>
              </div>
            </div>
          </section>

          {/* Compact key/value pairs - lead category, source, last contact,
              activity. Each row collapses cleanly when its value is
              missing so the drawer scales from sparse seed data to full
              records without empty placeholders. */}
          <dl className="grid grid-cols-[max-content_1fr] gap-x-4 gap-y-1.5 text-sm">
            {leadLabel ? (
              <>
                <dt className="text-muted-foreground">Lead</dt>
                <dd className="text-right font-medium">{leadLabel}</dd>
              </>
            ) : null}
            {sourceLabel ? (
              <>
                <dt className="text-muted-foreground">Source</dt>
                <dd className="text-right font-medium">{sourceLabel}</dd>
              </>
            ) : null}
            {lastContactDate ? (
              <>
                <dt className="text-muted-foreground">Last contact</dt>
                <dd className="text-right font-medium">{lastContactDate}</dd>
              </>
            ) : null}
            {activity ? (
              <>
                <dt className="text-muted-foreground">Last activity</dt>
                <dd className="text-right font-medium">{activity}</dd>
              </>
            ) : null}
          </dl>

          {notesPreview ? (
            <section>
              <p className="mb-1.5 text-xs font-medium uppercase tracking-wide text-muted-foreground">
                Notes
              </p>
              <p className="line-clamp-3 text-sm text-foreground/90 whitespace-pre-wrap">
                {notesPreview}
              </p>
            </section>
          ) : null}

          <Button asChild className="w-full" size="lg">
            <Link href={fullHref}>
              Open full page
              <ArrowRight className="ml-1.5 size-4" aria-hidden />
            </Link>
          </Button>
        </div>
      </SheetContent>
    </Sheet>
  );
}

function InterestSkeleton() {
  return (
    <div className="rounded-xl border border-border bg-card p-4 shadow-sm">
      <Skeleton className="h-4 w-32" aria-hidden />
      <Skeleton className="mt-2 h-3 w-24" aria-hidden />
      <Skeleton className="mt-3 h-2 w-48" aria-hidden />
    </div>
  );
}

interface ClientInterestsTabProps {
  clientId: string;
}

export function ClientInterestsTab({ clientId }: ClientInterestsTabProps) {
  const routeParams = useParams<{ portSlug: string }>();
  const portSlug = routeParams?.portSlug ?? '';
  const [createOpen, setCreateOpen] = useState(false);
  const [previewInterest, setPreviewInterest] = useState<ClientInterestRow | null>(null);

  const { data, isLoading, isError } = useClientInterests(clientId);

  if (isLoading) {
    return (
      <div className="space-y-3">
        <InterestSkeleton />
        <InterestSkeleton />
      </div>
    );
  }

  if (isError) {
    return <p className="text-sm text-destructive">Could not load interests for this client.</p>;
  }

  const interests = data?.data ?? [];

  if (interests.length === 0) {
    return (
      <>
        <EmptyState
          title="No interests yet"
          description="When this client expresses interest in a berth, the sales process will appear here."
          action={{
            label: 'Add interest',
            onClick: () => setCreateOpen(true),
          }}
        />
        <InterestForm open={createOpen} onOpenChange={setCreateOpen} defaultClientId={clientId} />
      </>
    );
  }

  const active = interests.filter((i) => !i.archivedAt);
  const archived = interests.filter((i) => i.archivedAt);

  return (
    <div className="space-y-6">
      <div className="flex justify-end">
        <Button size="sm" onClick={() => setCreateOpen(true)}>
          <Plus className="mr-1.5 size-3.5" aria-hidden />
          Add interest
        </Button>
      </div>

      {active.length > 0 ? (
        <div className="space-y-3">
          {active.map((i) => (
            <InterestRowItem key={i.id} interest={i} onOpen={setPreviewInterest} />
          ))}
        </div>
      ) : null}

      {archived.length > 0 ? (
        <div className="space-y-3">
          <h4 className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
            Archived
          </h4>
          <div className="space-y-3 opacity-60">
            {archived.map((i) => (
              <InterestRowItem key={i.id} interest={i} onOpen={setPreviewInterest} />
            ))}
          </div>
        </div>
      ) : null}

      <InterestPreviewSheet
        interest={previewInterest}
        portSlug={portSlug}
        onClose={() => setPreviewInterest(null)}
      />

      <InterestForm open={createOpen} onOpenChange={setCreateOpen} defaultClientId={clientId} />
    </div>
  );
}
