import { useEffect, useRef } from 'react';
import * as echarts from 'echarts/core';
import { GaugeChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
import type { EChartsType } from 'echarts/core';
import { buildEChartsTheme } from './buildEChartsTheme';
import { useThemeEpoch } from './useThemeEpoch';

echarts.use([GaugeChart, CanvasRenderer]);

interface TtlRingProps {
  deadline: string | null; // ISO timestamp
  size?: number;
}

export function TtlRing({ deadline, size = 80 }: TtlRingProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const chartRef = useRef<EChartsType | null>(null);
  const tickRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const themeEpoch = useThemeEpoch();

  useEffect(() => {
    if (!containerRef.current || !deadline) return;

    if (!chartRef.current) {
      const theme = buildEChartsTheme();
      chartRef.current = echarts.init(containerRef.current, theme);
    }

    const chart = chartRef.current;
    const root = getComputedStyle(document.documentElement);
    const get = (prop: string) => root.getPropertyValue(prop).trim();

    const maxMs = 3600_000; // 1h max ring

    const compute = () => {
      const remaining = new Date(deadline).getTime() - Date.now();
      const pct = Math.min(1, Math.max(0, remaining) / maxMs);
      // Derive gauge progress color from CSS custom properties
      let color = get('--glow-green');
      if (pct < 0.3) color = get('--glow-red');
      else if (pct < 0.6) color = get('--glow-amber');
      const minutes = Math.floor(remaining / 60_000);
      const seconds = Math.floor((remaining % 60_000) / 1000);
      const label = remaining > 0 ? `${minutes}m ${seconds}s` : 'expired';
      return { pct, color, label };
    };

    // Full structural option once. The static styling (axis, geometry, fonts)
    // never changes after this; ticks only merge the dynamic series fields.
    const initial = compute();
    chart.setOption({
      backgroundColor: 'transparent',
      series: [
        {
          type: 'gauge',
          startAngle: 220,
          endAngle: -40,
          min: 0,
          max: 1,
          radius: '90%',
          center: ['50%', '55%'],
          pointer: { show: false },
          progress: {
            show: true,
            overlap: false,
            roundCap: true,
            clip: false,
            itemStyle: { color: initial.color },
            width: 4,
          },
          axisLine: {
            lineStyle: {
              width: 4,
              color: [[1, get('--border')]],
            },
          },
          axisTick: { show: false },
          splitLine: { show: false },
          axisLabel: { show: false },
          title: { show: false },
          detail: {
            show: true,
            offsetCenter: ['0%', '5%'],
            fontSize: 11,
            fontWeight: 'bold',
            color: get('--foreground'),
            fontFamily: 'Orbitron',
            formatter: () => initial.label,
          },
          data: [{ value: initial.pct, name: 'TTL' }],
        },
      ],
    });

    // AUD2: per-tick merge update — only the changing series fields, not the
    // whole option tree, so the 1s timer stops rebuilding static geometry.
    const tick = () => {
      const { pct, color, label } = compute();
      chart.setOption({
        series: [
          {
            progress: { itemStyle: { color } },
            detail: { formatter: () => label },
            data: [{ value: pct, name: 'TTL' }],
          },
        ],
      });
    };
    tickRef.current = setInterval(tick, 1000);

    const observer = new ResizeObserver(() => chart.resize());
    observer.observe(containerRef.current);

    return () => {
      if (tickRef.current) clearInterval(tickRef.current);
      observer.disconnect();
      chart.dispose();
      chartRef.current = null;
    };
  }, [deadline, themeEpoch]);

  if (!deadline) return null;

  return (
    <div
      ref={containerRef}
      className="flex items-center justify-center"
      style={{ width: size, height: size }}
    />
  );
}
