import { useState, useEffect, useCallback, useMemo } from "react";
import { useDebounce } from "../useDebounce";
import useRoleService from "./useRoleService";
import {
  type Role,
  type Permission,
  type RolePermission,
  type GroupedPermissions,
  type RoleFilters,
  type CreateRoleData,
  type UpdateRoleData,
  type AssignPermissionData,
} from "../../services/roleService";

interface UseRoleState {
  roles: Role[];
  permissions: Permission[];
  rolePermissions: GroupedPermissions;
  rolePermissionsList: RolePermission[]; // Store the actual role-permissions list
  total: number;
  currentPage: number;
  totalPages: number;
  itemsPerPage: number;
  searchQuery: string;
  moduleFilter: string;
  loading: boolean;
  error: string | null;
}

interface UseRoleActions {
  setSearchQuery: (query: string) => void;
  setModuleFilter: (filter: string) => void;
  setCurrentPage: (page: number) => void;
  setItemsPerPage: (limit: number) => void;
  clearFilters: () => void;
  refreshData: () => Promise<void>;
  createRole: (data: CreateRoleData) => Promise<boolean>;
  updateRole: (data: UpdateRoleData) => Promise<boolean>;
  deleteRole: (id: number) => Promise<boolean>;
  toggleRoleStatus: (id: number) => Promise<boolean>;
  togglePermission: (roleId: number, permissionId: number) => Promise<boolean>;
  getRoleById: (id: number) => Promise<Role | null>;
  loadPermissions: () => Promise<void>;
  loadRolePermissions: () => Promise<void>;
  loadAllRolePermissions: () => Promise<void>;
  isPermissionGranted: (roleId: number, permissionId: number) => boolean;
}

const INITIAL_STATE: UseRoleState = {
  roles: [],
  permissions: [],
  rolePermissions: {},
  rolePermissionsList: [],
  total: 0,
  currentPage: 1,
  totalPages: 0,
  itemsPerPage: 100,
  searchQuery: "",
  moduleFilter: "all",
  loading: false,
  error: null,
};

function useRole() {
  const [state, setState] = useState<UseRoleState>(INITIAL_STATE);
  const service = useRoleService();

  // Debounce search query with 500ms delay
  const debouncedSearchQuery = useDebounce(state.searchQuery, 500);

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

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

      const result = await service.getRoles(filters);

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

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

    fetchRoles();
  }, [filters]);

  // Load permissions on component mount
  useEffect(() => {
    loadPermissions();
    loadRolePermissions();
    loadAllRolePermissions();
  }, []);

  // Action handlers
  const setSearchQuery = useCallback((query: string) => {
    setState((prev) => ({ ...prev, searchQuery: query, currentPage: 1 }));
  }, []);

  const setModuleFilter = useCallback((filter: string) => {
    setState((prev) => ({ ...prev, moduleFilter: filter }));
  }, []);

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

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

  const clearFilters = useCallback(() => {
    setState((prev) => ({
      ...prev,
      searchQuery: "",
      moduleFilter: "all",
      currentPage: 1,
    }));
  }, []);

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

    const result = await service.getRoles(filters);

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

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

  // Load permissions
  const loadPermissions = useCallback(async () => {
    const result = await service.getPermissions();
    if (result.success && result.data) {
      setState((prev) => ({
        ...prev,
        permissions: result.data!.data ?? [],
      }));
    }
  }, [service]);

  // Load role permissions
  const loadRolePermissions = useCallback(async () => {
    const result = await service.getRolePermissions();
    if (result.success && result.data) {
      setState((prev) => ({
        ...prev,
        rolePermissions: result.data!.data ?? {},
      }));
    }
  }, [service]);

  // Load all role permissions for management
  const loadAllRolePermissions = useCallback(async () => {
    const result = await service.getAllRolePermissions();
    if (result.success && result.data) {
      setState((prev) => ({
        ...prev,
        rolePermissionsList: result.data!.data?.data ?? [],
      }));
    }
  }, [service]);

  // Check if a permission is granted for a role
  const isPermissionGranted = useCallback(
    (roleId: number, permissionId: number): boolean => {
      return state.rolePermissionsList.some(
        (rp) =>
          rp.role_id === roleId &&
          rp.permission_id === permissionId &&
          rp.status === 1
      );
    },
    [state.rolePermissionsList]
  );

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

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

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

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

  const togglePermission = useCallback(
    async (roleId: number, permissionId: number): Promise<boolean> => {
      // Check if permission is currently granted
      const isCurrentlyGranted = isPermissionGranted(roleId, permissionId);

      let result;

      result = await service.assignPermission(roleId, {
        permission_id: permissionId,
      });

      if (result.success) {
        await loadAllRolePermissions(); // Reload all role permissions
      }
      return result.success;
    },
    [service, loadAllRolePermissions, isPermissionGranted]
  );

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

  const actions: UseRoleActions = {
    setSearchQuery,
    setModuleFilter,
    setCurrentPage,
    setItemsPerPage,
    clearFilters,
    refreshData,
    createRole,
    updateRole,
    deleteRole,
    toggleRoleStatus,
    togglePermission,
    getRoleById,
    loadPermissions,
    loadRolePermissions,
    loadAllRolePermissions,
    isPermissionGranted,
  };

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

export default useRole;
