'use client';
import { FunctionComponent, useEffect, useMemo, useRef, useState } from 'react';
import { useLocale } from 'next-intl';
import Box from '@mui/material/Box';
import CircularProgress from '@mui/material/CircularProgress';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import AppIcon from '@/components/common/AppIcon';
import { formatClock } from '@/utils';

export type CountdownTimerSize = 'sm' | 'md' | 'lg';

export interface CountdownTimerProps {
  /**
   * The **server-supplied** absolute UTC instant to count down to (e.g. `nurseResponseDeadlineAt`). The
   * client only renders the difference against `Date.now()` — it never computes or recomputes a deadline.
   */
  deadlineIso: string;
  /** Server-supplied UTC instant the window opened at. Supplying it renders the progress-ring variant. */
  windowStart?: string;
  /** Optional label above the digits (already translated by the caller). */
  label?: string;
  /** Shown once the deadline has passed — the poll then resolves the real terminal status. */
  elapsedText: string;
  /** Legacy override — forces the terracotta ("urgent") tier regardless of the thresholds below. Existing
   * consumers that always want the alarm treatment (a payment window) keep passing this unchanged; new
   * consumers should prefer the threshold props. */
  urgent?: boolean;
  /** Remaining-seconds threshold below which the accent shifts calm-teal → amber. Default 900 (15 min). */
  warnThresholdSeconds?: number;
  /** Remaining-seconds threshold below which the accent shifts amber → terracotta. Default 300 (5 min). */
  urgentThresholdSeconds?: number;
  /** Remaining-seconds threshold above which the humanized coarse mode renders instead of the ticking
   * clock. Default 600 (10 min). Has no effect unless `coarseLabel` is also supplied. */
  coarseThresholdSeconds?: number;
  /** Already-translated humanized minutes-remaining copy (e.g. `t('minutes_remaining', {minutes})`) —
   * supplying this opts into the coarse mode above `coarseThresholdSeconds`; omit to always show the
   * ticking clock (the pre-existing behavior). */
  coarseLabel?: (minutes: number) => string;
  size?: CountdownTimerSize;
  /** Fired once when the countdown reaches zero (e.g. to nudge a refetch). */
  onElapsed?: () => void;
}

const MS_PER_SECOND = 1000;
const SECONDS_PER_MINUTE = 60;
const DEFAULT_WARN_THRESHOLD = 900;
const DEFAULT_URGENT_THRESHOLD = 300;
const DEFAULT_COARSE_THRESHOLD = 600;

const RING_SIZE: Record<CountdownTimerSize, number> = { sm: 40, md: 56, lg: 72 };
const CLOCK_FONT_SIZE: Record<CountdownTimerSize, string> = { sm: '1.125rem', md: '1.5rem', lg: '2rem' };
const CLOCK_ICON_SIZE: Record<CountdownTimerSize, number> = { sm: 16, md: 20, lg: 24 };

/**
 * A pure presentational countdown to a server-frozen deadline. It owns its own one-second tick so only
 * this component re-renders each second — never the page around it. The ticking stops the moment the
 * deadline passes; crossing zero shows `elapsedText` and fires `onElapsed` once. Digits render in the
 * active locale (Persian for `fa`), forced LTR so the `HH:MM:SS` order is correct under RTL.
 *
 * v2 adds, all opt-in and backward compatible: a progress-ring variant (`windowStart`), three urgency
 * tiers (calm teal → amber → terracotta, via thresholds — `urgent` still force-overrides for the two
 * existing payment-window consumers), and a humanized coarse mode above `coarseThresholdSeconds`
 * (`coarseLabel`) with `aria-live="polite"` — applied only in coarse mode, since the fine ticking clock
 * updates every second and would spam assistive tech if announced.
 * @component CountdownTimer
 */
const CountdownTimer: FunctionComponent<CountdownTimerProps> = ({
  deadlineIso,
  windowStart,
  label,
  elapsedText,
  urgent,
  warnThresholdSeconds = DEFAULT_WARN_THRESHOLD,
  urgentThresholdSeconds = DEFAULT_URGENT_THRESHOLD,
  coarseThresholdSeconds = DEFAULT_COARSE_THRESHOLD,
  coarseLabel,
  size = 'md',
  onElapsed,
}) => {
  const locale = useLocale();
  const [now, setNow] = useState(() => Date.now());
  const target = useMemo(() => Date.parse(deadlineIso), [deadlineIso]);
  const start = useMemo(() => (windowStart ? Date.parse(windowStart) : undefined), [windowStart]);
  const remainingMs = Number.isFinite(target) ? Math.max(0, target - now) : 0;
  const elapsed = remainingMs <= 0;

  // Recreated only when `elapsed` flips (once) — not every tick, since `elapsed` stays false until zero.
  useEffect(() => {
    if (elapsed) return undefined;
    const interval = setInterval(() => setNow(Date.now()), MS_PER_SECOND);
    return () => clearInterval(interval);
  }, [elapsed]);

  const firedRef = useRef(false);
  useEffect(() => {
    if (elapsed && !firedRef.current) {
      firedRef.current = true;
      onElapsed?.();
    } else if (!elapsed) {
      firedRef.current = false;
    }
  }, [elapsed, onElapsed]);

  const remainingSeconds = Math.floor(remainingMs / MS_PER_SECOND);
  const accent =
    urgent !== undefined
      ? urgent
        ? 'var(--bal-secondary)'
        : 'var(--bal-primary)'
      : remainingSeconds <= urgentThresholdSeconds
        ? 'var(--bal-secondary)'
        : remainingSeconds <= warnThresholdSeconds
          ? 'var(--bal-warning)'
          : 'var(--bal-primary)';

  const isCoarse = Boolean(coarseLabel) && remainingSeconds >= coarseThresholdSeconds;
  const progressPercent =
    start !== undefined && Number.isFinite(start) && target - start > 0
      ? Math.min(100, Math.max(0, ((now - start) / (target - start)) * 100))
      : undefined;

  const content = elapsed ? (
    <Stack direction="row" sx={{ gap: 0.75, alignItems: 'center', color: 'text.secondary' }}>
      <AppIcon icon="schedule" size={CLOCK_ICON_SIZE[size]} color="var(--bal-text-secondary)" />
      <Typography variant="body2" sx={{ fontWeight: 500 }}>
        {elapsedText}
      </Typography>
    </Stack>
  ) : isCoarse ? (
    <Stack direction="row" sx={{ gap: 0.5, alignItems: 'center' }} aria-live="polite">
      <AppIcon icon="schedule" size={CLOCK_ICON_SIZE[size]} color={accent} />
      <Typography sx={{ fontWeight: 700, color: accent }}>
        {coarseLabel?.(Math.ceil(remainingSeconds / SECONDS_PER_MINUTE))}
      </Typography>
    </Stack>
  ) : (
    <Stack direction="row" sx={{ gap: 0.5, alignItems: 'center' }}>
      <AppIcon icon="schedule" size={CLOCK_ICON_SIZE[size]} color={accent} />
      <Typography
        component="span"
        dir="ltr"
        sx={{ fontWeight: 700, fontSize: CLOCK_FONT_SIZE[size], fontVariantNumeric: 'tabular-nums', color: accent }}
      >
        {formatClock(remainingSeconds, locale)}
      </Typography>
    </Stack>
  );

  const ring = (
    <Box sx={{ position: 'relative', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
      <CircularProgress
        variant="determinate"
        value={progressPercent}
        size={RING_SIZE[size]}
        thickness={3.5}
        sx={{ color: accent, '& .MuiCircularProgress-circle': { transition: 'stroke-dashoffset 0.3s linear' } }}
      />
      <Box sx={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <AppIcon icon="schedule" size={CLOCK_ICON_SIZE[size]} color={accent} />
      </Box>
    </Box>
  );

  return (
    <Stack sx={{ gap: 0.25, alignItems: 'center' }}>
      {label ? (
        <Typography variant="caption" sx={{ color: 'text.secondary', fontWeight: 500 }}>
          {label}
        </Typography>
      ) : null}
      {progressPercent === undefined ? (
        content
      ) : (
        <Stack sx={{ alignItems: 'center', gap: 0.75 }}>
          {ring}
          {content}
        </Stack>
      )}
    </Stack>
  );
};

export default CountdownTimer;
