import { Group, Loader, Text } from "@mantine/core";
import { Clock } from "lucide-react";
import { useEffect, useState } from "react";

export interface CountdownTimerProps {
  /** ISO timestamp the countdown targets. */
  deadline: string | null | undefined;
  /** Optional label shown before the time (e.g. "Window closes in"). */
  label?: string;
  /** Text shown once the deadline has passed. */
  expiredText?: string;
  /**
   * Optional grace stage: once `deadline` passes, count down to this later
   * ISO timestamp instead (e.g. the payment drain tail). `expiredText` then
   * only shows after the grace deadline has also passed.
   */
  graceDeadline?: string | null;
  /** Label shown while counting down the grace stage (e.g. "Payment processing — closes in"). */
  graceLabel?: string;
  /** Visual size of the time text. */
  size?: "xs" | "sm" | "md" | "lg";
  /** Colour once under this many seconds remain (urgency). Default 300 (5 min). */
  urgentUnderSeconds?: number;
}

function pad(n: number): string {
  return String(n).padStart(2, "0");
}

/** Break a remaining-milliseconds figure into a human string. */
function formatRemaining(ms: number): string {
  const total = Math.floor(ms / 1000);
  const days = Math.floor(total / 86400);
  const hours = Math.floor((total % 86400) / 3600);
  const minutes = Math.floor((total % 3600) / 60);
  const seconds = total % 60;

  if (days > 0) return `${days}d ${pad(hours)}h ${pad(minutes)}m`;
  if (hours > 0) return `${hours}h ${pad(minutes)}m ${pad(seconds)}s`;
  return `${pad(minutes)}m ${pad(seconds)}s`;
}

/**
 * Live countdown to an ISO deadline. Ticks once a second, shows the remaining
 * time (d/h/m/s), turns red when under `urgentUnderSeconds`, and shows
 * `expiredText` once the deadline is in the past. When `graceDeadline` is set,
 * a lapsed main deadline rolls into a calm second-stage countdown (spinner,
 * no urgency colours) toward it before `expiredText` takes over. Display only
 * — enforcement lives server-side.
 */
export function CountdownTimer({
  deadline,
  label,
  expiredText = "Expired",
  graceDeadline,
  graceLabel,
  size = "sm",
  urgentUnderSeconds = 300,
}: CountdownTimerProps) {
  const [now, setNow] = useState(() => Date.now());

  useEffect(() => {
    if (!deadline) return;
    setNow(Date.now());
    const id = setInterval(() => setNow(Date.now()), 1000);
    return () => clearInterval(id);
  }, [deadline, graceDeadline]);

  if (!deadline) return null;
  const target = new Date(deadline).getTime();
  if (Number.isNaN(target)) return null;

  const remaining = target - now;
  const expired = remaining <= 0;

  const graceTarget = graceDeadline ? new Date(graceDeadline).getTime() : NaN;
  const graceRemaining = Number.isNaN(graceTarget) ? 0 : graceTarget - now;
  const inGrace = expired && graceRemaining > 0;

  if (inGrace) {
    return (
      <Group gap={6} align="center" wrap="nowrap">
        <Loader size={size === "lg" ? 18 : 14} color="blue.7" />
        {graceLabel && (
          <Text size={size} c="dimmed">
            {graceLabel}
          </Text>
        )}
        <Text size={size} fw={600} c="blue.7">
          {formatRemaining(graceRemaining)}
        </Text>
      </Group>
    );
  }

  const urgent = !expired && remaining <= urgentUnderSeconds * 1000;
  const color = expired ? "red.7" : urgent ? "orange.7" : "dimmed";

  return (
    <Group gap={6} align="center" wrap="nowrap">
      <Clock size={size === "lg" ? 18 : 14} />
      {label && (
        <Text size={size} c="dimmed">
          {label}
        </Text>
      )}
      <Text size={size} fw={600} c={color}>
        {expired ? expiredText : formatRemaining(remaining)}
      </Text>
    </Group>
  );
}

export default CountdownTimer;
