import { useState, useCallback, useRef } from 'react';
import axios from 'axios';
import { WeekInfo } from '../types/shift';

interface AssignableShiftsCache {
  [key: string]: number[]; // key: `${userId}-${year}-${week}-${berId}`
}

const getCacheKey = (userId: number, year: number, week: number, berId: number | ''): string =>
  `${userId}-${year}-${week}-${berId}`;

interface UseAssignableShiftsResult {
  assignableShiftIds: Set<number> | null;
  isDragFiltering: boolean;
  fetchAssignableShifts: (userId: number) => Promise<void>;
  clearDragFilter: () => void;
}

export function useAssignableShifts(
  weekInfo: WeekInfo,
  selectedDepartment: number | '',
): UseAssignableShiftsResult {
  const [assignableShiftIds, setAssignableShiftIds] = useState<Set<number> | null>(null);
  const [isDragFiltering, setIsDragFiltering] = useState<boolean>(false);
  const cacheRef = useRef<AssignableShiftsCache>({});
  const lastWeekKeyRef = useRef<string>(`${weekInfo.year}-${weekInfo.week}`);

  // Invalidate cache when week changes
  const currentWeekKey = `${weekInfo.year}-${weekInfo.week}`;
  if (currentWeekKey !== lastWeekKeyRef.current) {
    cacheRef.current = {};
    lastWeekKeyRef.current = currentWeekKey;
  }

  const fetchAssignableShifts = useCallback(async (userId: number) => {
    const cacheKey = getCacheKey(userId, weekInfo.year, weekInfo.week, selectedDepartment);

    // Check cache first
    if (cacheRef.current[cacheKey]) {
      setAssignableShiftIds(new Set(cacheRef.current[cacheKey]));
      setIsDragFiltering(true);
      return;
    }

    setIsDragFiltering(true);

    try {
      const params: Record<string, any> = {
        user_id: userId,
        year: weekInfo.year,
        week: weekInfo.week,
      };
      if (selectedDepartment) {
        params.ber_id = selectedDepartment;
      }

      const response = await axios.get('/zeiterfassung/shifts/assignable', { params });
      const ids: number[] = response.data.assignable_shift_ids;

      // Store in cache
      cacheRef.current[cacheKey] = ids;
      setAssignableShiftIds(new Set(ids));
    } catch (error) {
      console.error('Failed to fetch assignable shifts:', error);
      // On error, don't filter — show all shifts
      setAssignableShiftIds(null);
      setIsDragFiltering(false);
    }
  }, [weekInfo.year, weekInfo.week, selectedDepartment]);

  const clearDragFilter = useCallback(() => {
    setAssignableShiftIds(null);
    setIsDragFiltering(false);
  }, []);

  return {
    assignableShiftIds,
    isDragFiltering,
    fetchAssignableShifts,
    clearDragFilter,
  };
}
