import { useState, useEffect, useCallback, useMemo } from "react";
import usePayrollService from "./usePayrollService";
import {
  type PayrollEntry,
  type PayrollEntryFilters,
  type UpdateAttendanceData,
} from "../../services/payrollService";

interface UsePayrollEntriesState {
  entries: PayrollEntry[];
  total: number;
  currentPage: number;
  totalPages: number;
  itemsPerPage: number;
  loading: boolean;
  error: string | null;
}

interface UsePayrollEntriesActions {
  setCurrentPage: (page: number) => void;
  setItemsPerPage: (items: number) => void;
  refreshData: () => Promise<void>;
  updateAttendance: (
    entryId: string,
    data: UpdateAttendanceData
  ) => Promise<boolean>;
}

const INITIAL_STATE: UsePayrollEntriesState = {
  entries: [],
  total: 0,
  currentPage: 1,
  totalPages: 0,
  itemsPerPage: 100,
  loading: false,
  error: null,
};

function usePayrollEntries(cycleId: string) {
  const [state, setState] = useState<UsePayrollEntriesState>(INITIAL_STATE);
  const service = usePayrollService();

  // Memoize filters to prevent unnecessary API calls
  const filters = useMemo<PayrollEntryFilters>(() => {
    return {
      page: state.currentPage,
      limit: state.itemsPerPage,
    };
  }, [state.currentPage, state.itemsPerPage]);

  // Auto-fetch when filters change or cycleId changes
  useEffect(() => {
    if (!cycleId) return;

    const fetchEntries = async () => {
      setState((prev) => ({ ...prev, loading: true, error: null }));

      const result = await service.getPayrollEntries(cycleId, filters);

      if (result.success && result.data) {
        // Handle the nested data structure: result.data.data contains pagination info
        const responseData: any = result.data.data;

        // Extract pagination info from the correct level
        const total = responseData?.total ?? 0;
        const limit = responseData?.limit ?? filters.limit ?? 10;
        const page = responseData?.page ?? state.currentPage;

        setState((prev) => ({
          ...prev,
          entries: responseData?.data ?? [],
          total,
          currentPage: page,
          totalPages: Math.ceil(total / limit),
          loading: false,
          error: null,
        }));
      } else {
        setState((prev) => ({
          ...prev,
          entries: [],
          total: 0,
          totalPages: 0,
          loading: false,
          error: result.message,
        }));
      }
    };

    fetchEntries();
  }, [cycleId, filters]);

  // Action handlers
  const setCurrentPage = useCallback((page: number) => {
    setState((prev) => ({ ...prev, currentPage: page }));
  }, []);

  const setItemsPerPage = useCallback((items: number) => {
    setState((prev) => ({ ...prev, itemsPerPage: items, currentPage: 1 }));
  }, []);

  // Refresh data
  const refreshData = useCallback(async () => {
    if (!cycleId) return;

    setState((prev) => ({ ...prev, loading: true, error: null }));

    const result = await service.getPayrollEntries(cycleId, filters);

    if (result.success && result.data) {
      // Handle the nested data structure: result.data.data contains pagination info
      const responseData: any = result.data.data;

      // Extract pagination info from the correct level
      const total = responseData?.total ?? 0;
      const limit = responseData?.limit ?? filters.limit ?? 10;
      const page = responseData?.page ?? state.currentPage;

      setState((prev) => ({
        ...prev,
        entries: responseData?.data ?? [],
        total,
        currentPage: page,
        totalPages: Math.ceil(total / limit),
        loading: false,
        error: null,
      }));
    } else {
      setState((prev) => ({
        ...prev,
        entries: [],
        total: 0,
        totalPages: 0,
        loading: false,
        error: result.message,
      }));
    }
  }, [cycleId, filters]);

  // Update attendance
  const updateAttendance = useCallback(
    async (entryId: string, data: UpdateAttendanceData): Promise<boolean> => {
      const result = await service.updatePayrollEntryAttendance(entryId, data);
      if (result.success) {
        await refreshData();
      }
      return result.success;
    },
    [service, refreshData]
  );

  const actions: UsePayrollEntriesActions = {
    setCurrentPage,
    setItemsPerPage,
    refreshData,
    updateAttendance,
  };

  return {
    ...state,
    loading: state.loading || service.loading,
    ...actions,
  };
}

export default usePayrollEntries;
