import { useState, useEffect, useCallback, useMemo } from "react";
import { useDebounce } from "../useDebounce";
import useLeaveRequestService from "./useLeaveRequestService";
import {
  type LeaveRequest,
  type LeaveRequestFilters,
  type CreateLeaveRequestData,
  type UpdateLeaveRequestData,
  type StatusChangeData,
} from "../../services/leaveRequestService";
import { useHasPermission } from "../usePermissions";

interface UseLeaveRequestState {
  leaveRequests: LeaveRequest[];
  total: number;
  currentPage: number;
  totalPages: number;
  itemsPerPage: number;
  searchTerm: string;
  statusFilter: "all" | "pending" | "approved" | "rejected" | "cancelled";
  typeFilter: string;
  departmentFilter: string;
  employeeFilter: string;
  fromDate: string;
  toDate: string;
  sortField: string | null;
  sortDirection: "ASC" | "DESC";
  loading: boolean;
  error: string | null;
  date?: string;
}

interface UseLeaveRequestActions {
  setSearchTerm: (term: string) => void;
  setStatusFilter: (
    filter: "all" | "pending" | "approved" | "rejected" | "cancelled"
  ) => void;
  setTypeFilter: (filter: string) => void;
  setDepartmentFilter: (filter: string) => void;
  setEmployeeFilter: (filter: string) => void;
  setFromDate: (date: string) => void;
  setToDate: (date: string) => void;
  setSortField: (field: string | null) => void;
  setSortDirection: (direction: "ASC" | "DESC") => void;
  setCurrentPage: (page: number) => void;
  setItemsPerPage: (items: number) => void;
  clearFilters: () => void;
  refreshData: () => Promise<void>;
  createLeaveRequest: (data: CreateLeaveRequestData) => Promise<boolean>;
  updateLeaveRequest: (data: UpdateLeaveRequestData) => Promise<boolean>;
  deleteLeaveRequest: (id: string) => Promise<boolean>;
  changeLeaveRequestStatus: (
    id: string,
    data: StatusChangeData
  ) => Promise<boolean>;
  getLeaveRequestById: (id: string) => Promise<LeaveRequest | null>;
}

const INITIAL_STATE: UseLeaveRequestState = {
  leaveRequests: [],
  total: 0,
  currentPage: 1,
  totalPages: 0,
  itemsPerPage: 100,
  searchTerm: "",
  statusFilter: "all",
  typeFilter: "all",
  departmentFilter: "all",
  employeeFilter: "all",
  fromDate: "",
  toDate: "",
  sortField: null,
  sortDirection: "ASC",
  loading: false,
  error: null,
  date: "all",
};

interface InitialFilters {
  employeeId?: string;
  status?: "pending" | "approved" | "rejected" | "cancelled";
  fromDate?: string;
  toDate?: string;
  date?: string;
}

function useLeaveRequest(initialFilters?: InitialFilters) {
  // Initialize state with initial filters if provided
  const [state, setState] = useState<UseLeaveRequestState>({
    ...INITIAL_STATE,
    employeeFilter: initialFilters?.employeeId || "all",
    statusFilter: initialFilters?.status || "all",
    fromDate: initialFilters?.fromDate || "",
    toDate: initialFilters?.toDate || "",
    date: initialFilters?.date || "all",
  });
  const service = useLeaveRequestService();
  const canApproveLeaves = useHasPermission("approve_leaves");

  // Debounce search term with 500ms delay
  const debouncedSearchTerm = useDebounce(state.searchTerm, 500);

  // Memoize filters to prevent unnecessary API calls
  const filters = useMemo<LeaveRequestFilters>(() => {
    return {
      search: debouncedSearchTerm,
      leave_type_id: state.typeFilter !== "all" ? state.typeFilter : undefined,
      department_id:
        state.departmentFilter !== "all" ? state.departmentFilter : undefined,
      employee_id:
        state.employeeFilter !== "all" ? state.employeeFilter : undefined,
      status: state.statusFilter !== "all" ? state.statusFilter : undefined,
      from_date: state.fromDate || undefined,
      to_date: state.toDate || undefined,
      date: state.date && state.date !== "all" ? state.date : undefined,
      column_name: state.sortField || undefined,
      order: state.sortField ? state.sortDirection : undefined,
      page: state.currentPage,
      limit: state.itemsPerPage,
      showAll: canApproveLeaves ? true : false,
    };
  }, [
    debouncedSearchTerm,
    state.typeFilter,
    state.departmentFilter,
    state.employeeFilter,
    state.statusFilter,
    state.fromDate,
    state.toDate,
    state.date,
    state.sortField,
    state.sortDirection,
    state.currentPage,
    state.itemsPerPage,
    canApproveLeaves,
  ]);

  // Auto-fetch when filters change
  useEffect(() => {
    const fetchLeaveRequests = async () => {
      setState((prev) => ({ ...prev, loading: true, error: null }));

      const result = await service.getLeaveRequests(filters);

      if (result.success && result.data) {
        const total = result.data.data?.count ?? 0;
        const limit = filters.limit ?? 10;

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

    fetchLeaveRequests();
  }, [filters]);

  // Action handlers
  const setSearchTerm = useCallback((term: string) => {
    setState((prev) => ({ ...prev, searchTerm: term, currentPage: 1 }));
  }, []);

  const setStatusFilter = useCallback(
    (filter: "all" | "pending" | "approved" | "rejected" | "cancelled") => {
      setState((prev) => ({ ...prev, statusFilter: filter, currentPage: 1 }));
    },
    []
  );

  const setTypeFilter = useCallback((filter: string) => {
    setState((prev) => ({ ...prev, typeFilter: filter, currentPage: 1 }));
  }, []);

  const setDepartmentFilter = useCallback((filter: string) => {
    setState((prev) => ({ ...prev, departmentFilter: filter, currentPage: 1 }));
  }, []);

  const setEmployeeFilter = useCallback((filter: string) => {
    setState((prev) => ({ ...prev, employeeFilter: filter, currentPage: 1 }));
  }, []);

  const setFromDate = useCallback((date: string) => {
    setState((prev) => ({ ...prev, fromDate: date, currentPage: 1 }));
  }, []);

  const setToDate = useCallback((date: string) => {
    setState((prev) => ({ ...prev, toDate: date, currentPage: 1 }));
  }, []);

  const setSortField = useCallback((field: string | null) => {
    setState((prev) => ({ ...prev, sortField: field }));
  }, []);

  const setSortDirection = useCallback((direction: "ASC" | "DESC") => {
    setState((prev) => ({ ...prev, sortDirection: direction }));
  }, []);

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

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

  // Clear only filter dropdowns; do not clear search
  const clearFilters = useCallback(() => {
    setState((prev) => ({
      ...prev,
      statusFilter: "all",
      typeFilter: "all",
      departmentFilter: "all",
      employeeFilter: initialFilters?.employeeId || "all",
      fromDate: "",
      toDate: "",
      currentPage: 1,
    }));
  }, [initialFilters?.employeeId]);

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

    const result = await service.getLeaveRequests(filters);

    if (result.success && result.data) {
      const total = result.data.data?.count ?? 0;
      const limit = filters.limit ?? 10;

      setState((prev) => ({
        ...prev,
        leaveRequests: result.data!.data?.data ?? [],
        total,
        totalPages: Math.ceil(total / limit),
        loading: false,
        error: null,
      }));
    } else {
      setState((prev) => ({
        ...prev,
        leaveRequests: [],
        total: 0,
        totalPages: 0,
        loading: false,
        error: result.message,
      }));
    }
  }, [service, filters]);

  // CRUD operations
  const createLeaveRequest = useCallback(
    async (data: CreateLeaveRequestData): Promise<boolean> => {
      const result = await service.createLeaveRequest(data);
      if (result.success) {
        await refreshData();
      }
      return result.success;
    },
    [service, refreshData]
  );

  const updateLeaveRequest = useCallback(
    async (data: UpdateLeaveRequestData): Promise<boolean> => {
      const result = await service.updateLeaveRequest(data);
      if (result.success) {
        await refreshData();
      }
      return result.success;
    },
    [service, refreshData]
  );

  const deleteLeaveRequest = useCallback(
    async (id: string): Promise<boolean> => {
      const result = await service.deleteLeaveRequest(id);
      if (result.success) {
        await refreshData();
      }
      return result.success;
    },
    [service, refreshData]
  );

  const changeLeaveRequestStatus = useCallback(
    async (id: string, data: StatusChangeData): Promise<boolean> => {
      const result = await service.changeLeaveRequestStatus(id, data);
      if (result.success) {
        await refreshData();
      }
      return result.success;
    },
    [service, refreshData]
  );

  const getLeaveRequestById = useCallback(
    async (id: string): Promise<LeaveRequest | null> => {
      const result = await service.getLeaveRequestById(id);
      return result.success && result.data ? result.data.data : null;
    },
    [service]
  );

  const actions: UseLeaveRequestActions = {
    setSearchTerm,
    setStatusFilter,
    setTypeFilter,
    setDepartmentFilter,
    setEmployeeFilter,
    setFromDate,
    setToDate,
    setSortField,
    setSortDirection,
    setCurrentPage,
    setItemsPerPage,
    clearFilters,
    refreshData,
    createLeaveRequest,
    updateLeaveRequest,
    deleteLeaveRequest,
    changeLeaveRequestStatus,
    getLeaveRequestById,
  };

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

export default useLeaveRequest;
