'use client';

import { useState, useEffect, useCallback, useRef } from 'react';
import api from '@/lib/api';

interface UseSwipeOptions {
  onSwipeLeft?: () => void;
  onSwipeRight?: () => void;
  onSwipeUp?: () => void;
  onSwipeDown?: () => void;
  threshold?: number;
}

export function useSwipe({
  onSwipeLeft,
  onSwipeRight,
  onSwipeUp,
  onSwipeDown,
  threshold = 50,
}: UseSwipeOptions) {
  const touchStart = useRef<{ x: number; y: number } | null>(null);
  const touchEnd = useRef<{ x: number; y: number } | null>(null);

  const handleTouchStart = useCallback((e: React.TouchEvent) => {
    touchStart.current = { x: e.touches[0].clientX, y: e.touches[0].clientY };
  }, []);

  const handleTouchMove = useCallback((e: React.TouchEvent) => {
    touchEnd.current = { x: e.touches[0].clientX, y: e.touches[0].clientY };
  }, []);

  const handleTouchEnd = useCallback(() => {
    if (!touchStart.current || !touchEnd.current) return;

    const diffX = touchEnd.current.x - touchStart.current.x;
    const diffY = touchEnd.current.y - touchStart.current.y;

    if (Math.abs(diffX) > Math.abs(diffY)) {
      if (Math.abs(diffX) > threshold) {
        if (diffX > 0 && onSwipeRight) {
          onSwipeRight();
        } else if (diffX < 0 && onSwipeLeft) {
          onSwipeLeft();
        }
      }
    } else {
      if (Math.abs(diffY) > threshold) {
        if (diffY > 0 && onSwipeDown) {
          onSwipeDown();
        } else if (diffY < 0 && onSwipeUp) {
          onSwipeUp();
        }
      }
    }

    touchStart.current = null;
    touchEnd.current = null;
  }, [onSwipeLeft, onSwipeRight, onSwipeUp, onSwipeDown, threshold]);

  return {
    handleTouchStart,
    handleTouchMove,
    handleTouchEnd,
  };
}

export function useTimer(initialMinutes: number = 0) {
  const [seconds, setSeconds] = useState(initialMinutes * 60);
  const [isRunning, setIsRunning] = useState(false);
  const [isPaused, setIsPaused] = useState(false);
  const intervalRef = useRef<NodeJS.Timeout | null>(null);

  useEffect(() => {
    if (isRunning && !isPaused && seconds > 0) {
      intervalRef.current = setInterval(() => {
        setSeconds((s) => Math.max(0, s - 1));
      }, 1000);
    }

    return () => {
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
      }
    };
  }, [isRunning, isPaused, seconds]);

  const start = useCallback(() => {
    setIsRunning(true);
    setIsPaused(false);
  }, []);

  const pause = useCallback(() => {
    setIsPaused(true);
  }, []);

  const resume = useCallback(() => {
    setIsPaused(false);
  }, []);

  const reset = useCallback((minutes?: number) => {
    setSeconds((minutes ?? initialMinutes) * 60);
    setIsRunning(false);
    setIsPaused(false);
  }, [initialMinutes]);

  const formatTime = useCallback((totalSeconds: number) => {
    const mins = Math.floor(totalSeconds / 60);
    const secs = totalSeconds % 60;
    return `${mins}:${secs.toString().padStart(2, '0')}`;
  }, []);

  return {
    seconds,
    isRunning,
    isPaused,
    start,
    pause,
    resume,
    reset,
    formattedTime: formatTime(seconds),
  };
}

export function useActiveSession() {
  const [session, setSession] = useState<{
    id: string;
    routineId: string;
    routineName: string;
    routineIcon?: string;
    status: string;
    currentStepIndex: number;
  } | null>(null);
  const [currentStep, setCurrentStep] = useState<{
    id: string;
    name: string;
    instructions?: string;
    stepType: string;
    durationMinutes?: number;
    position: number;
  } | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const fetchActiveSession = useCallback(async () => {
    setIsLoading(true);
    setError(null);
    try {
      const data = await api.sessions.getActive();
      if (data.session && data.current_step) {
        setSession({
          id: data.session.id,
          routineId: data.session.routine_id,
          routineName: data.routine.name,
          routineIcon: data.routine.icon,
          status: data.session.status,
          currentStepIndex: data.session.current_step_index,
        });
        setCurrentStep({
          id: data.current_step.id,
          name: data.current_step.name,
          instructions: data.current_step.instructions,
          stepType: data.current_step.step_type,
          durationMinutes: data.current_step.duration_minutes,
          position: data.current_step.position,
        });
      }
    } catch (err) {
      if ((err as Error).message !== 'no active session') {
        setError((err as Error).message);
      }
    } finally {
      setIsLoading(false);
    }
  }, []);

  const completeStep = useCallback(async () => {
    if (!session) return;
    try {
      const result = await api.sessions.completeStep(session.id, currentStep!.id);
      if (result.next_step) {
        setCurrentStep({
          id: result.next_step.id,
          name: result.next_step.name,
          instructions: result.next_step.instructions,
          stepType: result.next_step.step_type,
          durationMinutes: result.next_step.duration_minutes,
          position: result.next_step.position,
        });
        setSession((s) => s ? { ...s, currentStepIndex: result.session.current_step_index! } : null);
      } else {
        setSession(null);
        setCurrentStep(null);
      }
    } catch (err) {
      setError((err as Error).message);
    }
  }, [session, currentStep]);

  const skipStep = useCallback(async () => {
    if (!session) return;
    try {
      const result = await api.sessions.skipStep(session.id, currentStep!.id);
      if (result.next_step) {
        setCurrentStep({
          id: result.next_step.id,
          name: result.next_step.name,
          instructions: result.next_step.instructions,
          stepType: result.next_step.step_type,
          durationMinutes: result.next_step.duration_minutes,
          position: result.next_step.position,
        });
        setSession((s) => s ? { ...s, currentStepIndex: result.session.current_step_index! } : null);
      } else {
        setSession(null);
        setCurrentStep(null);
      }
    } catch (err) {
      setError((err as Error).message);
    }
  }, [session, currentStep]);

  const pause = useCallback(async () => {
    if (!session) return;
    try {
      await api.sessions.pause(session.id);
      setSession((s) => s ? { ...s, status: 'paused' } : null);
    } catch (err) {
      setError((err as Error).message);
    }
  }, [session]);

  const resume = useCallback(async () => {
    if (!session) return;
    try {
      await api.sessions.resume(session.id);
      setSession((s) => s ? { ...s, status: 'active' } : null);
    } catch (err) {
      setError((err as Error).message);
    }
  }, [session]);

  const cancel = useCallback(async () => {
    if (!session) return;
    try {
      await api.sessions.cancel(session.id);
      setSession(null);
      setCurrentStep(null);
    } catch (err) {
      setError((err as Error).message);
    }
  }, [session]);

  return {
    session,
    currentStep,
    isLoading,
    error,
    fetchActiveSession,
    completeStep,
    skipStep,
    pause,
    resume,
    cancel,
  };
}
