import { useState, useEffect, useCallback } from "react";

interface TimeFormat {
  days: number;
  hours: number;
  minutes: number;
  seconds: number;
}

class TimeUtils {
  static getTimeFromSeconds(seconds: number): TimeFormat {
    const days = Math.floor(seconds / (60 * 60 * 24));
    const hours = Math.floor((seconds % (60 * 60 * 24)) / (60 * 60));
    const minutes = Math.floor((seconds % (60 * 60)) / 60);
    const secs = Math.floor(seconds % 60);

    return { days, hours, minutes, seconds: secs };
  }

  static getSecondsFromExpiry(expiry: Date): number {
    const now = new Date().getTime();
    const expiryTime = expiry.getTime();

    return Math.max(0, (expiryTime - now) / 1000);
  }
}

interface UseTimerProps {
  expiryTimestamp: Date;
  onExpire?: () => void;
  autoStart?: boolean;
}

interface UseTimerReturn extends TimeFormat {
  isRunning: boolean;
  pause: () => void;
  resume: () => void;
  restart: (newExpiryTimestamp: Date) => void;
}

const useTimer = ({
  expiryTimestamp,
  onExpire,
  autoStart = true,
}: UseTimerProps): UseTimerReturn => {
  const [isRunning, setIsRunning] = useState<boolean>(autoStart);
  const [seconds, setSeconds] = useState<number>(
    TimeUtils.getSecondsFromExpiry(expiryTimestamp),
  );

  const tick = useCallback(() => {
    const newSeconds = TimeUtils.getSecondsFromExpiry(expiryTimestamp);
    if (newSeconds <= 0) {
      if (onExpire) onExpire();
      setIsRunning(false);
    }
    setSeconds(newSeconds);
  }, [expiryTimestamp, onExpire]);

  useEffect(() => {
    if (!isRunning) return;
    const intervalId = setInterval(tick, 1000);
    return () => clearInterval(intervalId);
  }, [isRunning, tick]);

  const pause = useCallback(() => setIsRunning(false), []);
  const resume = useCallback(() => setIsRunning(true), []);
  const restart = useCallback((newExpiryTimestamp: Date) => {
    setIsRunning(true);
    setSeconds(TimeUtils.getSecondsFromExpiry(newExpiryTimestamp));
  }, []);

  return {
    ...TimeUtils.getTimeFromSeconds(seconds),
    isRunning,
    pause,
    resume,
    restart,
  };
};

export default useTimer;
