import { useState } from 'react';
import { Link } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import {
  ArrowRight,
  ArrowRightLeft,
  LogIn,
  LogOut,
  Pencil,
  type LucideIcon,
} from 'lucide-react';
import { Button, Skeleton } from '@vector/ui';
import { listHostTimeline } from '../../lib/api/hosts.js';
import { queryKeys } from '../../lib/queryKeys.js';
import type { HostTimelineEntry } from '../../lib/api/types.js';

const ENTRY_ICON: Record<HostTimelineEntry['type'], LucideIcon> = {
  HOST_EVENT: Pencil,
  REPAIR: ArrowRightLeft,
  PART_ARRIVED: LogIn,
  PART_DEPARTED: LogOut,
};

const HOST_EVENT_TITLE: Record<string, string> = {
  CREATED: 'Created',
  STATE_CHANGED: 'State changed',
  STACK_CHANGED: 'Stack changed',
  FIELD_UPDATED: 'Field updated',
};

function formatWhen(iso: string) {
  return new Date(iso).toLocaleString(undefined, {
    month: 'short',
    day: 'numeric',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  });
}

function EntryRow({ entry }: { entry: HostTimelineEntry }) {
  switch (entry.type) {
    case 'HOST_EVENT': {
      const { hostEvent } = entry;
      return (
        <>
          <div className="flex flex-wrap items-center gap-x-2 text-sm">
            <span className="font-medium text-foreground">
              {HOST_EVENT_TITLE[hostEvent.type] ?? hostEvent.type}
            </span>
            {hostEvent.field && (
              <span className="text-xs text-muted-foreground">· {hostEvent.field}</span>
            )}
            {(hostEvent.oldValue || hostEvent.newValue) && (
              <span className="inline-flex items-center gap-1 text-xs text-muted-foreground">
                <span className="font-mono">{hostEvent.oldValue ?? '—'}</span>
                <ArrowRight className="h-3 w-3" />
                <span className="font-mono text-foreground">{hostEvent.newValue ?? '—'}</span>
              </span>
            )}
          </div>
          <div className="mt-0.5 text-xs text-muted-foreground">
            {formatWhen(entry.at)}
            {hostEvent.user?.username ? ` · ${hostEvent.user.username}` : ''}
          </div>
        </>
      );
    }
    case 'REPAIR': {
      const { repair } = entry;
      return (
        <>
          <div className="flex flex-wrap items-center gap-x-2 text-sm">
            <span className="font-medium text-foreground">Repair</span>
            <span className="inline-flex flex-wrap items-center gap-1 text-xs">
              <Link
                to={`/parts/${repair.brokenPart.id}`}
                className="font-mono text-muted-foreground hover:underline"
              >
                {repair.brokenPart.serialNumber}
              </Link>
              <span className="text-muted-foreground">→ BROKEN</span>
              <span className="text-muted-foreground">·</span>
              <Link
                to={`/parts/${repair.replacement.id}`}
                className="font-mono text-foreground hover:underline"
              >
                {repair.replacement.serialNumber}
              </Link>
              <span className="text-muted-foreground">→ DEPLOYED</span>
            </span>
          </div>
          <div className="mt-0.5 text-xs text-muted-foreground">
            {formatWhen(entry.at)}
            {repair.performedBy?.username ? ` · ${repair.performedBy.username}` : ''}
          </div>
        </>
      );
    }
    case 'PART_ARRIVED':
    case 'PART_DEPARTED': {
      const { part } = entry;
      const label = entry.type === 'PART_ARRIVED' ? 'Part deployed' : 'Part departed';
      return (
        <>
          <div className="flex flex-wrap items-center gap-x-2 text-sm">
            <span className="font-medium text-foreground">{label}</span>
            <Link
              to={`/parts/${part.id}`}
              className="font-mono text-xs text-muted-foreground hover:underline"
            >
              {part.serialNumber}
            </Link>
            <span className="text-xs text-muted-foreground">· {part.mpn}</span>
          </div>
          <div className="mt-0.5 text-xs text-muted-foreground">{formatWhen(entry.at)}</div>
        </>
      );
    }
  }
}

function entryKey(entry: HostTimelineEntry): string {
  switch (entry.type) {
    case 'HOST_EVENT':
      return `he-${entry.hostEvent.id}`;
    case 'REPAIR':
      return `r-${entry.repair.id}`;
    case 'PART_ARRIVED':
      return `pa-${entry.partEventId}`;
    case 'PART_DEPARTED':
      return `pd-${entry.partEventId}`;
  }
}

export function HostTimeline({ hostId }: { hostId: string }) {
  const [page, setPage] = useState(1);
  const pageSize = 20;
  const query = useQuery({
    queryKey: queryKeys.hosts.timeline(hostId, { page, pageSize }),
    queryFn: () => listHostTimeline(hostId, { page, pageSize }),
    placeholderData: (prev) => prev,
  });

  if (query.isPending) {
    return (
      <div className="space-y-2">
        {Array.from({ length: 4 }).map((_, i) => (
          <Skeleton key={i} className="h-12 w-full" />
        ))}
      </div>
    );
  }

  if (query.isError) {
    return <p className="text-sm text-destructive">Could not load history.</p>;
  }

  const entries = query.data?.data ?? [];
  const total = query.data?.total ?? 0;
  const pageCount = Math.max(1, Math.ceil(total / pageSize));

  if (entries.length === 0) {
    return <p className="text-sm text-muted-foreground">No activity yet.</p>;
  }

  return (
    <div className="space-y-1">
      <ol className="relative ml-3 border-l border-border">
        {entries.map((entry) => {
          const Icon = ENTRY_ICON[entry.type];
          return (
            <li key={entryKey(entry)} className="relative pl-6 pb-4 last:pb-0">
              <span className="absolute -left-[11px] top-0 flex h-5 w-5 items-center justify-center rounded-full border border-border bg-background">
                <Icon className="h-3 w-3 text-muted-foreground" />
              </span>
              <EntryRow entry={entry} />
            </li>
          );
        })}
      </ol>

      {pageCount > 1 && (
        <div className="flex items-center justify-end gap-2 pt-2 text-xs text-muted-foreground">
          <span>
            Page {page} of {pageCount}
          </span>
          <Button
            variant="ghost"
            size="sm"
            className="h-7"
            disabled={page <= 1 || query.isFetching}
            onClick={() => setPage(page - 1)}
          >
            Previous
          </Button>
          <Button
            variant="ghost"
            size="sm"
            className="h-7"
            disabled={page >= pageCount || query.isFetching}
            onClick={() => setPage(page + 1)}
          >
            Next
          </Button>
        </div>
      )}
    </div>
  );
}
