import { useQuery } from "@tanstack/react-query";
import { History } from "lucide-react";
import { Badge, Group, Loader, Stack, Text, Timeline } from "@mantine/core";
import type { Freight } from "@edr/types";

import { contractsService } from "@/services/contracts.service";
import { SectionCard } from "@/components/bookings/detail/SectionCard";

interface ContractRevisionTimelineProps {
  contractId: string;
}

type Change = Freight.IContractDocumentChange;

/** Badge colour + verb per change kind, so a revision reads at a glance. */
const CHANGE_STYLES: Record<Change["kind"], { color: string; label: string }> = {
  ARTICLE_ADDED: { color: "green", label: "Added" },
  ARTICLE_REMOVED: { color: "red", label: "Removed" },
  ARTICLE_RENAMED: { color: "violet", label: "Renamed" },
  ARTICLE_BODY_CHANGED: { color: "blue", label: "Edited" },
  ARTICLE_REORDERED: { color: "gray", label: "Reordered" },
  DOCUMENT_TITLE_CHANGED: { color: "grape", label: "Title" },
  WHEREAS_CHANGED: { color: "teal", label: "Recitals" },
};

/** What the change applies to — an article title, or the document itself. */
function changeSubject(change: Change): string {
  switch (change.kind) {
    case "DOCUMENT_TITLE_CHANGED":
      return change.fromTitle
        ? `“${change.fromTitle}” → “${change.title}”`
        : change.title;
    case "WHEREAS_CHANGED": {
      const parts: string[] = [];
      if (change.added) parts.push(`+${change.added}`);
      if (change.removed) parts.push(`−${change.removed}`);
      return parts.join(" ") || "changed";
    }
    case "ARTICLE_RENAMED":
      return `“${change.fromTitle}” → “${change.title}”`;
    case "ARTICLE_REORDERED":
      return `${change.title} (${change.fromOrder} → ${change.toOrder})`;
    default:
      return change.title;
  }
}

function formatWhen(iso: string): string {
  const date = new Date(iso);
  return date.toLocaleString(undefined, {
    dateStyle: "medium",
    timeStyle: "short",
  });
}

/**
 * Audit trail of edits to the contract document. The document stays editable
 * through the approval chain, so this is the record of who changed what.
 */
export function ContractRevisionTimeline({
  contractId,
}: ContractRevisionTimelineProps) {
  const { data: revisions, isLoading } = useQuery({
    queryKey: ["contracts", contractId, "document-revisions"],
    queryFn: () => contractsService.getContractDocumentRevisions(contractId),
  });

  return (
    <SectionCard icon={History} title="Document history">
      {isLoading ? (
        <Group gap="xs">
          <Loader size="xs" />
          <Text size="sm" c="dimmed">
            Loading history…
          </Text>
        </Group>
      ) : !revisions?.length ? (
        <Text size="sm" c="dimmed">
          No edits recorded yet. Changes made to the contract articles during
          approval will appear here.
        </Text>
      ) : (
        <Timeline
          active={revisions.length}
          bulletSize={18}
          lineWidth={2}
          color="edr-green"
        >
          {revisions.map((revision) => (
            <Timeline.Item
              key={revision.id}
              title={
                <Group gap="xs" wrap="nowrap">
                  <Text size="sm" fw={600}>
                    {revision.actorRole ?? "Staff"}
                  </Text>
                  <Text size="xs" c="dimmed">
                    {formatWhen(revision.createdAt)}
                  </Text>
                </Group>
              }
            >
              <Stack gap={6} mt={4}>
                {revision.summary && (
                  <Text size="xs" c="dimmed">
                    {revision.summary}
                  </Text>
                )}
                {revision.changes.map((change, index) => {
                  const style = CHANGE_STYLES[change.kind];
                  return (
                    <Group key={index} gap="xs" wrap="nowrap" align="flex-start">
                      <Badge
                        size="xs"
                        variant="light"
                        color={style?.color ?? "gray"}
                        style={{ flexShrink: 0 }}
                      >
                        {style?.label ?? change.kind}
                      </Badge>
                      <Text size="xs" style={{ lineHeight: 1.5 }}>
                        {changeSubject(change)}
                      </Text>
                    </Group>
                  );
                })}
              </Stack>
            </Timeline.Item>
          ))}
        </Timeline>
      )}
    </SectionCard>
  );
}
