import { useMemo } from "react";
import {
  BadgeCheck,
  CalendarClock,
  Flame,
  Send,
  ShieldCheck,
  FileSignature,
} from "lucide-react";
import { Group, Stack, Text, Timeline, Tooltip } from "@mantine/core";
import type { Freight } from "@edr/types";

import { formatDate } from "@/lib/format";
import {
  CONTRACT_APPROVAL_ROLE_LABELS,
  HAZARDOUS_APPROVAL_ROLE_PERMISSION,
} from "@/lib/permissions";

interface ContractMilestonesTimelineProps {
  contract: Freight.IContract;
}

const SIGNATURE_ROLE_LABELS: Record<Freight.ContractSignatureRole, string> = {
  CUSTOMER: "Signed by customer",
  STAFF: "Signed by EDR — line staff",
  DIRECTOR: "Signed by EDR — director",
  CEO: "Signed by EDR — CEO",
};

/** "27 Jul 2026, 18:18" — the exact stamp, shown in the tooltip. */
function formatWhen(iso: string): string {
  return new Date(iso).toLocaleString(undefined, {
    dateStyle: "medium",
    timeStyle: "short",
  });
}

/** "3 hours ago" — the at-a-glance read. */
function formatAgo(iso: string): string {
  const seconds = Math.round((Date.now() - new Date(iso).getTime()) / 1000);
  if (seconds < 60) return "just now";
  const units: Array<[Intl.RelativeTimeFormatUnit, number]> = [
    ["year", 31536000],
    ["month", 2592000],
    ["day", 86400],
    ["hour", 3600],
    ["minute", 60],
  ];
  const rtf = new Intl.RelativeTimeFormat(undefined, { numeric: "auto" });
  for (const [unit, secondsPerUnit] of units) {
    if (seconds >= secondsPerUnit) {
      return rtf.format(-Math.floor(seconds / secondsPerUnit), unit);
    }
  }
  return "just now";
}

type MilestoneIcon = typeof Send;

interface Milestone {
  key: string;
  at: string;
  title: string;
  detail?: string;
  color: string;
  icon: MilestoneIcon;
}

/**
 * The dated moments of a contract's life — submission, hazardous approval,
 * final approval, both parties' signatures, full execution — read straight off
 * the contract and its already-loaded approvalSteps/signatures (no extra
 * fetch). Sits above the document edit history on the History tab.
 */
export function ContractMilestonesTimeline({
  contract,
}: ContractMilestonesTimelineProps) {
  const milestones = useMemo<Milestone[]>(() => {
    const items: Milestone[] = [];

    // A DRAFT/RENEWAL_DRAFT contract hasn't been (re)submitted yet — nothing
    // to date. submittedAt is only tracked going forward; a contract that
    // reached SUBMITTED before that column existed falls back to createdAt.
    const submittedAt =
      contract.submittedAt ??
      (contract.status !== "DRAFT" && contract.status !== "RENEWAL_DRAFT"
        ? contract.createdAt
        : null);
    if (submittedAt) {
      items.push({
        key: "submitted",
        at: submittedAt,
        title: "Submitted for review",
        color: "blue",
        icon: Send,
      });
    }

    // Every acted approval step, not just hazardous ones — this is the one
    // place the approval-time record shows up in the page's main content
    // (the sidebar's ContractApprovalStepsCard has the same times, but only
    // there, and only while the chain is still actionable).
    for (const step of contract.approvalSteps ?? []) {
      if (!step.actedAt) continue;
      const hazard = step.requiredRole in HAZARDOUS_APPROVAL_ROLE_PERMISSION;
      items.push({
        key: `step-${step.id}`,
        at: step.actedAt,
        title: `${CONTRACT_APPROVAL_ROLE_LABELS[step.requiredRole] ?? step.requiredRole} ${step.status === "REJECTED" ? "rejected" : "approved"}`,
        detail: step.note ?? undefined,
        color: step.status === "REJECTED" ? "red" : hazard ? "orange" : "edr-green",
        icon: hazard ? Flame : ShieldCheck,
      });
    }

    if (contract.contractGeneratedAt) {
      items.push({
        key: "approved",
        at: contract.contractGeneratedAt,
        title: "Contract approved",
        detail: "Every approval step cleared and the document was generated",
        color: "edr-green",
        icon: ShieldCheck,
      });
    }

    for (const sig of contract.signatures ?? []) {
      items.push({
        key: `signature-${sig.id}`,
        at: sig.signedAt,
        title: SIGNATURE_ROLE_LABELS[sig.role] ?? `Signed by ${sig.role}`,
        detail: sig.signerDisplayName,
        color: "grape",
        icon: FileSignature,
      });
    }

    if (contract.fullyExecutedAt) {
      items.push({
        key: "executed",
        at: contract.fullyExecutedAt,
        title: "Fully executed",
        detail: "Both parties have signed",
        color: "edr-green",
        icon: BadgeCheck,
      });
    }

    return items.sort(
      (a, b) => new Date(a.at).getTime() - new Date(b.at).getTime(),
    );
  }, [contract]);

  const hasValidity = contract.contractValidFrom && contract.contractValidUntil;

  if (milestones.length === 0 && !hasValidity) {
    return (
      <Text size="sm" c="dimmed" ta="center" py="lg">
        No dated milestones recorded yet.
      </Text>
    );
  }

  return (
    <Stack gap="md">
      {hasValidity && (
        <Group
          gap="xs"
          px="sm"
          py="xs"
          style={{
            borderRadius: 8,
            border: "1px solid var(--mantine-color-gray-2)",
            background: "var(--mantine-color-gray-0)",
            width: "fit-content",
          }}
        >
          <CalendarClock size={16} color="var(--mantine-color-gray-6)" />
          <Text size="sm">
            Valid <strong>{formatDate(contract.contractValidFrom!)}</strong>
            {" → "}
            <strong>{formatDate(contract.contractValidUntil!)}</strong>
          </Text>
        </Group>
      )}

      {milestones.length > 0 && (
        <Timeline active={milestones.length} bulletSize={26} lineWidth={2} color="edr-green">
          {milestones.map((m) => {
            const Icon = m.icon;
            return (
              <Timeline.Item
                key={m.key}
                bullet={<Icon size={13} />}
                color={m.color}
                title={
                  <Group gap="xs" wrap="wrap" align="baseline">
                    <Text size="sm" fw={600}>
                      {m.title}
                    </Text>
                    <Tooltip label={formatWhen(m.at)} withArrow>
                      <Text size="xs" c="dimmed">
                        {formatAgo(m.at)}
                      </Text>
                    </Tooltip>
                  </Group>
                }
              >
                {m.detail && (
                  <Text size="xs" c="dimmed" mt={2}>
                    {m.detail}
                  </Text>
                )}
              </Timeline.Item>
            );
          })}
        </Timeline>
      )}
    </Stack>
  );
}
