import { useState, useCallback, useEffect, useMemo, useRef } from "react";
import { useDebounce } from "../useDebounce";
import useTimeTrackingService from "./useTimeTrackingService";
import {
  type TimeEntry,
  type TimeTrackingFilters,
  type CreateTimeEntryData,
  type UpdateTimeEntryData,
} from "../../services/timeTrackingService";

interface UseTimeTrackingState {
  timeEntries: TimeEntry[];
  total: number;
  currentPage: number;
  totalPages: number;
  itemsPerPage: number;
  searchTerm: string;
  projectFilter: string;
  activityTypeFilter: string;
  order: "ASC" | "DESC" | "";
  columnName: string | null;
  loading: boolean;
  error: string | null;
}

interface UseTimeTrackingActions {
  setSearchTerm: (term: string) => void;
  setProjectFilter: (filter: string) => void;
  setActivityTypeFilter: (filter: string) => void;
  setOrder: (order: "ASC" | "DESC" | "") => void;
  setColumnName: (columnName: string | null) => void;
  setCurrentPage: (page: number) => void;
  setItemsPerPage: (items: number) => void;
  clearFilters: () => void;
  refreshData: () => Promise<void>;
  createTimeEntry: (data: CreateTimeEntryData) => Promise<boolean>;
  updateTimeEntry: (data: UpdateTimeEntryData) => Promise<boolean>;
  stopTimeEntry: (id: string) => Promise<boolean>;
  deleteTimeEntry: (id: string) => Promise<boolean>;
  getTimeEntryById: (id: string) => Promise<TimeEntry | null>;
}

const INITIAL_STATE: UseTimeTrackingState = {
  timeEntries: [],
  total: 0,
  currentPage: 1,
  totalPages: 0,
  itemsPerPage: 100,
  searchTerm: "",
  projectFilter: "all",
  activityTypeFilter: "all",
  order: "",
  columnName: null,
  loading: false,
  error: null,
};

function useTimeTracking() {
  const [state, setState] = useState<UseTimeTrackingState>(INITIAL_STATE);
  const service = useTimeTrackingService();

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

  // Memoize filters to prevent unnecessary API calls
  const filters = useMemo<TimeTrackingFilters>(() => {
    const result: TimeTrackingFilters = {
      search: debouncedSearchTerm,
      page: state.currentPage,
      limit: state.itemsPerPage,
    };

    if (state.projectFilter !== "all") {
      result.project_id = state.projectFilter;
    }

    if (state.activityTypeFilter !== "all") {
      result.activity_type_id = state.activityTypeFilter;
    }

    if (state.order && state.columnName) {
      result.order = state.order;
      result.column_name = state.columnName;
    }

    return result;
  }, [
    debouncedSearchTerm,
    state.projectFilter,
    state.activityTypeFilter,
    state.currentPage,
    state.itemsPerPage,
    state.order,
    state.columnName,
  ]);

  // Fetch time entries
  const fetchTimeEntries = useCallback(async () => {
    setState((prev) => ({ ...prev, loading: true, error: null }));

    const result = await service.getTimeEntries(filters);

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

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

  // Use ref to track previous filters and prevent duplicate fetches
  const prevFiltersRef = useRef<string>("");

  // Auto-fetch when filters change
  useEffect(() => {
    // Serialize filters to compare
    const filtersKey = JSON.stringify(filters);
    
    // Only fetch if filters have actually changed
    if (prevFiltersRef.current !== filtersKey) {
      prevFiltersRef.current = filtersKey;
      // Inline fetch to avoid dependency on fetchTimeEntries
      (async () => {
        setState((prev) => ({ ...prev, loading: true, error: null }));

        const result = await service.getTimeEntries(filters);

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

          setState((prev) => ({
            ...prev,
            timeEntries: result?.data?.data?.data ?? [],
            total,
            totalPages: Math.ceil(total / limit),
            loading: false,
            error: null,
          }));
        } else {
          setState((prev) => ({
            ...prev,
            timeEntries: [],
            total: 0,
            totalPages: 0,
            loading: false,
            error: result.message,
          }));
        }
      })();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    debouncedSearchTerm,
    state.projectFilter,
    state.activityTypeFilter,
    state.currentPage,
    state.itemsPerPage,
    state.order,
    state.columnName,
  ]);

  // Refresh data
  const refreshData = useCallback(async () => {
    await fetchTimeEntries();
  }, [fetchTimeEntries]);

  // Filter setters
  const setSearchTerm = useCallback((term: string) => {
    setState((prev) => ({
      ...prev,
      searchTerm: term,
      currentPage: 1, // Reset to first page when searching
    }));
  }, []);

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

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

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

  const setColumnName = useCallback((columnName: string | null) => {
    setState((prev) => ({ ...prev, columnName }));
  }, []);

  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 (project, activity type); do not clear search
  const clearFilters = useCallback(() => {
    setState((prev) => ({
      ...prev,
      projectFilter: "all",
      activityTypeFilter: "all",
      currentPage: 1,
    }));
  }, []);

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

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

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

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

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

  const actions: UseTimeTrackingActions = {
    setSearchTerm,
    setProjectFilter,
    setActivityTypeFilter,
    setOrder,
    setColumnName,
    setCurrentPage,
    setItemsPerPage,
    clearFilters,
    refreshData,
    createTimeEntry,
    updateTimeEntry,
    stopTimeEntry,
    deleteTimeEntry,
    getTimeEntryById,
  };

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

export default useTimeTracking;
