import { useState, useEffect, useCallback, useMemo } from 'react';
import apiService from '../services/apiService';

interface RestrictionInfo {
  field: string;
  values: string[];
  count: number;
}

interface PermissionsState {
  isAdmin: boolean;
  restrictions: Record<string, RestrictionInfo>;
  permissionFilters: Record<string, any>;
  targetDoctype: string;
  loading: boolean;
  error: string | null;
}

/**
 * Generic hook for user permissions - works with ANY doctype
 * 
 * Usage:
 *   const { permissionFilters, restrictions } = useUserPermissions('Asset');
 *   const { permissionFilters, restrictions } = useUserPermissions('Work Order');
 *   const { permissionFilters, restrictions } = useUserPermissions('Project');
 */
export const useUserPermissions = (targetDoctype: string = 'Asset') => {
  const [state, setState] = useState<PermissionsState>({
    isAdmin: false,
    restrictions: {},
    permissionFilters: {},
    targetDoctype,
    loading: true,
    error: null
  });

  const fetchPermissions = useCallback(async (doctype?: string) => {
    const dt = doctype || targetDoctype;
    
    try {
      setState(prev => ({ ...prev, loading: true, error: null, targetDoctype: dt }));

      const response = await apiService.getPermissionFilters(dt);

      setState({
        isAdmin: response.is_admin,
        restrictions: response.restrictions || {},
        permissionFilters: response.filters || {},
        targetDoctype: dt,
        loading: false,
        error: null
      });

      return response;
    } catch (err) {
      console.error(`Error fetching permissions for ${dt}:`, err);
      setState(prev => ({
        ...prev,
        loading: false,
        error: err instanceof Error ? err.message : 'Failed to fetch permissions'
      }));
      return null;
    }
  }, [targetDoctype]);

  useEffect(() => {
    fetchPermissions();
  }, [fetchPermissions]);

  // Get allowed values for a permission type (e.g., "Company", "Location")
  const getAllowedValues = useCallback((permissionType: string): string[] => {
    return state.restrictions[permissionType]?.values || [];
  }, [state.restrictions]);

  // Check if user has restriction on a permission type
  const hasRestriction = useCallback((permissionType: string): boolean => {
    if (state.isAdmin) return false;
    return !!state.restrictions[permissionType];
  }, [state.isAdmin, state.restrictions]);

  // Check if any restrictions exist
  const hasAnyRestrictions = useMemo(() => {
    return !state.isAdmin && Object.keys(state.restrictions).length > 0;
  }, [state.isAdmin, state.restrictions]);

  // Merge user filters with permission filters
  const mergeFilters = useCallback((userFilters: Record<string, any>): Record<string, any> => {
    if (state.isAdmin) return userFilters;
    
    const merged = { ...userFilters };
    
    for (const [field, value] of Object.entries(state.permissionFilters)) {
      if (!merged[field]) {
        merged[field] = value;
      } else if (Array.isArray(value) && value[0] === 'in') {
        const permittedValues = value[1] as string[];
        if (typeof merged[field] === 'string' && !permittedValues.includes(merged[field])) {
          merged[field] = ['in', []]; // Return empty - value not permitted
        }
      }
    }
    
    return merged;
  }, [state.isAdmin, state.permissionFilters]);

  // Get summary of restrictions for display
  const restrictionsList = useMemo(() => {
    return Object.entries(state.restrictions).map(([type, info]) => ({
      type,
      field: info.field,
      values: info.values,
      count: info.count
    }));
  }, [state.restrictions]);

  return {
    ...state,
    refetch: fetchPermissions,
    switchDoctype: fetchPermissions,
    getAllowedValues,
    hasRestriction,
    hasAnyRestrictions,
    mergeFilters,
    restrictionsList
  };
};

/**
 * Hook to check access to a specific document
 */
export const useDocumentAccess = (doctype: string | null, docname: string | null) => {
  const [hasAccess, setHasAccess] = useState<boolean | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!doctype || !docname) {
      setHasAccess(null);
      return;
    }

    const check = async () => {
      try {
        setLoading(true);
        const response = await apiService.checkDocumentAccess(doctype, docname);
        setHasAccess(response.has_access);
        if (!response.has_access && response.error) {
          setError(response.error);
        }
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to check access');
        setHasAccess(false);
      } finally {
        setLoading(false);
      }
    };

    check();
  }, [doctype, docname]);

  return { hasAccess, loading, error };
};

/**
 * Hook to get user's default values
 */
export const useUserDefaults = () => {
  const [defaults, setDefaults] = useState<Record<string, string>>({});
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetch = async () => {
      try {
        const response = await apiService.getUserDefaults();
        setDefaults(response.defaults || {});
      } catch (err) {
        console.error('Failed to fetch user defaults:', err);
      } finally {
        setLoading(false);
      }
    };
    fetch();
  }, []);

  return { defaults, loading, getDefault: (type: string) => defaults[type] };
};

export default useUserPermissions;