import {
  useState,
  useRef,
  useCallback,
  useEffect,
  forwardRef,
  useImperativeHandle,
} from 'react';

// ─────────────────────────────────────────────────────────────
// Imperative handle
// ─────────────────────────────────────────────────────────────

export interface TimerHandle {
  start: () => void;
  stop: () => void;
  getElapsed: () => number; // returns elapsed seconds
}

// ─────────────────────────────────────────────────────────────
// Helpers
// ─────────────────────────────────────────────────────────────

function formatMMSS(totalSeconds: number): string {
  const m = Math.floor(totalSeconds / 60);
  const s = Math.floor(totalSeconds % 60);
  return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
}

function storageKey(caseId: string | number): string {
  return `timer_case_${caseId}`;
}

interface StoredTimer {
  startTimestamp: number; // Date.now() when started
  accumulated: number; // seconds accumulated before last start
}

function readStorage(caseId: string | number): StoredTimer | null {
  try {
    const raw = localStorage.getItem(storageKey(caseId));
    if (!raw) return null;
    return JSON.parse(raw) as StoredTimer;
  } catch {
    return null;
  }
}

function writeStorage(caseId: string | number, data: StoredTimer): void {
  try {
    localStorage.setItem(storageKey(caseId), JSON.stringify(data));
  } catch {
    // localStorage unavailable
  }
}

export function clearTimerStorage(caseId: string | number): void {
  try {
    localStorage.removeItem(storageKey(caseId));
  } catch {
    // ignore
  }
}

// ─────────────────────────────────────────────────────────────
// Props
// ─────────────────────────────────────────────────────────────

interface TimerProps {
  caseId: string | number;
}

// ─────────────────────────────────────────────────────────────
// Component
// ─────────────────────────────────────────────────────────────

const Timer = forwardRef<TimerHandle, TimerProps>(({ caseId }, ref) => {
  const [displaySeconds, setDisplaySeconds] = useState<number>(0);

  // Mutable refs to avoid re-renders on tick
  const isRunningRef = useRef(false);
  const accumulatedRef = useRef(0);
  const startTimestampRef = useRef<number | null>(null);
  const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);

  // ── Restore from localStorage on mount ─────────────────────
  useEffect(() => {
    const stored = readStorage(caseId);
    if (stored) {
      accumulatedRef.current = stored.accumulated;

      // If the timer was running when the page closed, treat startTimestamp
      // as the new start point but keep the accumulated time.
      if (stored.startTimestamp > 0) {
        const elapsedSinceStore =
          Math.floor((Date.now() - stored.startTimestamp) / 1000);
        const total = stored.accumulated + elapsedSinceStore;
        accumulatedRef.current = total;
        setDisplaySeconds(total);
        // Don't auto-start — the parent must call start() explicitly
      } else {
        setDisplaySeconds(stored.accumulated);
      }
    }
  }, [caseId]);

  // ── Imperative API ────────────────────────────────────────

  const start = useCallback(() => {
    if (isRunningRef.current) return; // already running

    isRunningRef.current = true;
    startTimestampRef.current = Date.now();

    // Persist: store startTimestamp + accumulated so far
    writeStorage(caseId, {
      startTimestamp: startTimestampRef.current,
      accumulated: accumulatedRef.current,
    });

    // Mostrar valor actual INMEDIATAMENTE (sin esperar 1s al primer tick)
    setDisplaySeconds(accumulatedRef.current);

    intervalRef.current = setInterval(() => {
      if (startTimestampRef.current === null) return;
      const elapsed = Math.floor(
        (Date.now() - startTimestampRef.current) / 1000,
      );
      const total = accumulatedRef.current + elapsed;
      setDisplaySeconds(total);
    }, 1000);
  }, [caseId]);

  const stop = useCallback(() => {
    if (!isRunningRef.current) return;

    isRunningRef.current = false;

    if (intervalRef.current) {
      clearInterval(intervalRef.current);
      intervalRef.current = null;
    }

    // Finalize accumulated time
    if (startTimestampRef.current !== null) {
      const elapsed = Math.floor(
        (Date.now() - startTimestampRef.current) / 1000,
      );
      accumulatedRef.current += elapsed;
      startTimestampRef.current = null;
    }

    // Persist: accumulated with no running timer
    writeStorage(caseId, {
      startTimestamp: 0,
      accumulated: accumulatedRef.current,
    });

    setDisplaySeconds(accumulatedRef.current);
  }, [caseId]);

  const getElapsed = useCallback((): number => {
    if (isRunningRef.current && startTimestampRef.current !== null) {
      const elapsed = Math.floor(
        (Date.now() - startTimestampRef.current) / 1000,
      );
      return accumulatedRef.current + elapsed;
    }
    return accumulatedRef.current;
  }, []);

  useImperativeHandle(ref, () => ({ start, stop, getElapsed }), [
    start,
    stop,
    getElapsed,
  ]);

  // ── Cleanup on unmount ────────────────────────────────────
  useEffect(() => {
    return () => {
      // 1. Primero: persistir estado vía stop() (ya es idempotente)
      stop();
      // 2. Segundo: anular el intervalo (por si stop no lo hizo)
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
        intervalRef.current = null;
      }
      // 3. Tercero: resetear bandera (para StrictMode)
      isRunningRef.current = false;
    };
  }, [stop]);

  // ── Render ────────────────────────────────────────────────

  return (
    <span className="font-mono text-xl font-bold text-text-primary tabular-nums">
      {formatMMSS(displaySeconds)}
    </span>
  );
});

Timer.displayName = 'Timer';

export default Timer;
