import { useState, useEffect, useCallback } from 'react';
import { useApiRequest } from './useApi';
import { setUserDataCache, getUserDataCache, clearUserDataCache } from '../utils/userCache';
import api from '../api';
import { usePermissions, type UserPermissions } from './usePermissions';
import {
  fetchCurrentUser as fetchCurrentUserApi,
  logoutUser as logoutUserApi,
  fetchUsers as fetchUsersApi,
  fetchUserById as fetchUserByIdApi,
  createUser as createUserApi,
  updateUser as updateUserApi,
  deleteUser as deleteUserApi,
  sendPasswordLink as sendPasswordLinkApi,
  type User,
  type UserUpdateData,
  type AttributeDefinition,
  type PaginationParams
} from '../api/userApi';

// Re-export types for backward compatibility
export type { User, UserUpdateData, AttributeDefinition, PaginationParams };

// Current user hook
export function useCurrentUser() {
  const [user, setUser] = useState<User | null>(null);
  const { request, isLoading, error } = useApiRequest<null, User>();

  const fetchCurrentUser = async (retryCount = 0) => {
    try {
      // Check if we already have user data in sessionStorage cache
      const cachedUser = getUserDataCache();
      if (cachedUser && cachedUser.username) {
        // Use cached user data - permissions are checked via RBAC API, not client-side
        // Note: roleLabels is deprecated in Multi-Tenant architecture - use isSysAdmin flag instead
        setUser(cachedUser);
        console.log('✅ Using cached user data from sessionStorage (persists during session):', {
          username: cachedUser.username,
          isSysAdmin: cachedUser.isSysAdmin
        });
        return;
      }
      
      // JWT tokens are now stored in httpOnly cookies, so we fetch user data from API
      console.log('🍪 JWT tokens are in httpOnly cookies, fetching user data from API');
      
      // Determine the correct endpoint based on authentication authority
      const authAuthority = sessionStorage.getItem('auth_authority');
      let endpoint = '/api/local/me';
      
      if (authAuthority === 'msft') {
        endpoint = '/api/msft/me';
      } else if (authAuthority === 'google') {
        endpoint = '/api/google/me';
      }
      
      console.log('🔍 Fetching user data from API:', { 
        endpoint, 
        authAuthority, 
        hasAuthCookies: document.cookie.includes('access_token') || document.cookie.includes('refresh_token')
      });
      
      // Add a small delay to ensure cookies are properly set after authentication
      if (authAuthority === 'msft' || authAuthority === 'google') {
        console.log('⏳ Adding delay for OAuth authentication cookie propagation...');
        await new Promise(resolve => setTimeout(resolve, 500));
      }
      
      const data = await fetchCurrentUserApi(request, authAuthority || undefined);
      
      // Log response for debugging
      console.log('📦 User data received from API:', {
        username: data?.username,
        isSysAdmin: data?.isSysAdmin,
        allKeys: data ? Object.keys(data) : []
      });
      
      // Validate user data
      if (!data || !data.username) {
        console.error('❌ User data from API is invalid:', {
          username: data?.username,
          dataKeys: data ? Object.keys(data) : []
        });
        throw new Error('Invalid user data received from API');
      }
      
      // Cache user data (permissions are checked via RBAC API)
      // Note: roleLabels is deprecated - use isSysAdmin flag for admin checks
      setUserDataCache(data);
      console.log('✅ User data fetched from API and cached:', {
        username: data.username,
        isSysAdmin: data.isSysAdmin
      });
      setUser(data);
    } catch (error: any) {
      console.error('❌ Failed to fetch user data:', error);
      
      // Display debug information if this is a Microsoft/Google auth failure
      const authAuthority = sessionStorage.getItem('auth_authority');
      if (authAuthority === 'msft' || authAuthority === 'google') {
        console.log('🔧 Current state:', {
          authAuthority,
          currentCookies: document.cookie || 'No cookies',
          hasAccessToken: document.cookie.includes('access_token'),
          hasRefreshToken: document.cookie.includes('refresh_token'),
          retryCount,
          error: error.message
        });
      }
      
      // If authentication failed and we haven't retried yet, try again after a delay
      const isOAuth = authAuthority === 'msft' || authAuthority === 'google';
      const maxRetries = isOAuth ? 2 : 0; // Only retry for OAuth
      
      if (retryCount < maxRetries && (error.message?.includes('Not authenticated') || error.message?.includes('Request aborted'))) {
        console.log(`🔄 Retrying user data fetch (attempt ${retryCount + 1}/${maxRetries + 1}) in 2 seconds...`);
        setTimeout(() => {
          fetchCurrentUser(retryCount + 1);
        }, 2000);
        return;
      }
      
      // If all retries failed or this is not a retryable error
      setUser(null);
      clearUserDataCache();
      
      // If authentication failed after all retries, clear auth data
      if (error.message?.includes('Not authenticated') || error.message?.includes('401')) {
        console.log('🔐 Authentication failed after retries - clearing auth data');
        
        // Clear auth authority
        sessionStorage.removeItem('auth_authority');
        clearUserDataCache();
        
        // Trigger a redirect to login by forcing a page reload
        setTimeout(() => {
          window.location.href = '/login';
        }, 1000);
      }
    }
  };

  const logout = async (msalInstance?: any) => {
    if (!user) {
      throw new Error('No user to logout');
    }

    try {
      // Determine the correct logout endpoint based on authentication authority
      // Note: logoutEndpoint is determined by logoutUserApi based on authenticationAuthority

      await logoutUserApi(request, user.authenticationAuthority);

      console.log('✅ Logout API call completed, waiting for browser to process cookies...');
      
      // CRITICAL: Wait for browser to process Set-Cookie headers from logout response
      // This gives the browser time to clear httpOnly cookies before redirect
      await new Promise(resolve => setTimeout(resolve, 1000));

      // Clear user state after successful logout
      setUser(null);
      
      // CRITICAL: Clear all authentication data BEFORE any redirects
      // This ensures cleanup happens even if MSAL redirect interrupts the process
      console.log('🧹 Starting comprehensive cleanup...');
      
      // Clear user data cache from sessionStorage
      clearUserDataCache();
      
      // Clear auth authority from sessionStorage
      sessionStorage.removeItem('auth_authority');
      
      // Clear MSAL cache tokens from localStorage
      // MSAL stores tokens with keys starting with 'msal.'
      const keysToRemove = [];
      for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i);
        if (key && (
          key.startsWith('msal.') || 
          key === 'auth_token' || 
          key === 'refresh_token' ||
          key.includes('token') ||
          key.includes('auth') ||
          key.includes('msal')
        )) {
          keysToRemove.push(key);
        }
      }
      keysToRemove.forEach(key => {
        console.log('🗑️ Removing token:', key);
        localStorage.removeItem(key);
      });
      
      // Clear ALL MSAL cache data (including account keys, token keys, version)
      const msalKeysToRemove = [];
      for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i);
        if (key && key.startsWith('msal.')) {
          msalKeysToRemove.push(key);
        }
      }
      msalKeysToRemove.forEach(key => {
        console.log('🗑️ Removing MSAL cache:', key);
        localStorage.removeItem(key);
      });
      
      // Clear sessionStorage as well (CSRF tokens, etc.)
      sessionStorage.clear();
      
      // Clear cookies as backup (in case backend doesn't clear them properly)
      // Note: This only works for cookies that are accessible to JavaScript
      console.log('🍪 Checking cookies for cleanup...');
      console.log('🍪 All cookies:', document.cookie);
      
      const cookies = document.cookie.split(";");
      console.log('🍪 Cookie count:', cookies.length);
      
      cookies.forEach(function(c) { 
        const cookieName = c.split("=")[0].trim();
        console.log('🍪 Checking cookie:', cookieName);
        
        if (cookieName === 'auth_token' || cookieName === 'refresh_token' || cookieName.includes('token') || cookieName.includes('msal')) {
          console.log('🗑️ Clearing cookie:', cookieName);
          document.cookie = cookieName + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
        }
      });
      
      console.log('🍪 Cookies after cleanup attempt:', document.cookie);
      
      console.log('✅ Cleanup completed');
      
      // Handle MSAL logout for Microsoft authentication
      if (user.authenticationAuthority === 'msft' && msalInstance) {
        try {
          console.log('🔄 Starting MSAL logout redirect...');
          await msalInstance.logoutRedirect({
            onRedirectNavigate: () => {
              console.log('🔄 MSAL redirect initiated - cleanup already completed');
              return true;
            }
          });
          return; // MSAL will handle the redirect
        } catch (msalError) {
          console.error('MSAL logout failed:', msalError);
          // Continue with regular redirect if MSAL logout fails
        }
      }
      
      // Redirect to login or home page
      console.log('🔄 Redirecting to login page...');
      window.location.href = '/login';
      
    } catch (error) {
      console.error('Logout failed:', error);
      throw error;
    }
  };

  useEffect(() => {
    // Try to load user from sessionStorage cache first for faster initial load
    const cachedUser = getUserDataCache();
    if (cachedUser && cachedUser.username) {
      // Use cached user data - permissions are checked via RBAC API
      // Note: roleLabels is deprecated in Multi-Tenant architecture - use isSysAdmin flag instead
      setUser(cachedUser);
      console.log('✅ Using cached user data from sessionStorage on mount:', {
        username: cachedUser.username,
        isSysAdmin: cachedUser.isSysAdmin
      });
    }
    
    // For OAuth authentication, wait a bit longer before fetching user data
    const authAuthority = sessionStorage.getItem('auth_authority');
    const isOAuth = authAuthority === 'msft' || authAuthority === 'google';
    
    if (isOAuth) {
      console.log('⏳ OAuth authentication detected, delaying user data fetch...');
      // Wait for authentication cookies to be properly set
      const timer = setTimeout(() => {
        fetchCurrentUser();
      }, 1000);
      
      return () => clearTimeout(timer);
    } else {
      // For local authentication, fetch immediately
      fetchCurrentUser();
    }
  }, []);

  return {
    user,
    error,
    isLoading,
    refetch: fetchCurrentUser,
    logout
  };
}

// Re-export AttributeOption for backward compatibility
export interface AttributeOption {
  value: string | number;
  label: string | { [key: string]: string };
}

// Organization users hook (list, update, delete) - following prompts/workflows pattern
export function useOrgUsers() {
  const [users, setUsers] = useState<User[]>([]);
  const [attributes, setAttributes] = useState<AttributeDefinition[]>([]);
  const [permissions, setPermissions] = useState<UserPermissions | null>(null);
  const [pagination, setPagination] = useState<{
    currentPage: number;
    pageSize: number;
    totalItems: number;
    totalPages: number;
  } | null>(null);
  const { request, isLoading: loading, error } = useApiRequest<null, User[]>();
  const { checkPermission } = usePermissions();

  // Fetch attributes from backend
  const fetchAttributes = useCallback(async () => {
    try {
      const response = await api.get('/api/attributes/User');
      
      // Extract attributes from response
      let attrs: AttributeDefinition[] = [];
      if (response.data?.attributes && Array.isArray(response.data.attributes)) {
        attrs = response.data.attributes;
      } else if (Array.isArray(response.data)) {
        attrs = response.data;
      } else if (response.data && typeof response.data === 'object') {
        const keys = Object.keys(response.data);
        for (const key of keys) {
          if (Array.isArray(response.data[key])) {
            attrs = response.data[key];
            break;
          }
        }
      }
      
      setAttributes(attrs);
      return attrs;
    } catch (error: any) {
      // Don't log 429 errors as errors (they're rate limit warnings)
      if (error.response?.status === 429) {
        console.warn('Rate limit exceeded while fetching user attributes. Please wait.');
      } else if (error.response?.status !== 401) {
        // Only log non-auth errors (401 is expected when not logged in)
        console.error('Error fetching attributes:', error);
      }
      setAttributes([]);
      return [];
    }
  }, []);

  // Fetch permissions from backend
  const fetchPermissions = useCallback(async () => {
    try {
      const perms = await checkPermission('DATA', 'User');
      setPermissions(perms);
      return perms;
    } catch (error: any) {
      console.error('Error fetching permissions:', error);
      const defaultPerms: UserPermissions = {
        view: false,
        read: 'n',
        create: 'n',
        update: 'n',
        delete: 'n',
      };
      setPermissions(defaultPerms);
      return defaultPerms;
    }
  }, [checkPermission]);

  const fetchUsers = useCallback(async (params?: PaginationParams) => {
    try {
      const requestParams: any = {};
      
      // Build pagination object if provided
      if (params) {
        const paginationObj: any = {};
        
        if (params.page !== undefined) paginationObj.page = params.page;
        if (params.pageSize !== undefined) paginationObj.pageSize = params.pageSize;
        if (params.sort) paginationObj.sort = params.sort;
        if (params.filters) paginationObj.filters = params.filters;
        if (params.search) paginationObj.search = params.search;
        
        if (Object.keys(paginationObj).length > 0) {
          requestParams.pagination = JSON.stringify(paginationObj);
        }
      }
      
      const data = await fetchUsersApi(request, params);
      
      // Handle paginated response
      if (data && typeof data === 'object' && 'items' in data) {
        const items = Array.isArray(data.items) ? data.items : [];
        setUsers(items);
        if (data.pagination) {
          setPagination(data.pagination);
        }
      } else {
        // Handle non-paginated response (backward compatibility)
        const items = Array.isArray(data) ? data : [];
        setUsers(items);
        setPagination(null);
      }
    } catch (error: any) {
      // Error is already handled by useApiRequest
      setUsers([]);
      setPagination(null);
    }
  }, [request]);

  // Optimistically remove a user from the local state
  const removeOptimistically = (userId: string) => {
    setUsers(prevUsers => prevUsers.filter(user => user.id !== userId));
  };

  // Optimistically update a user in the local state
  const updateOptimistically = (userId: string, updateData: Partial<User>) => {
    setUsers(prevUsers => 
      prevUsers.map(user => 
        user.id === userId 
          ? { ...user, ...updateData }
          : user
      )
    );
  };

  // Fetch a single user by ID
  const fetchUserById = useCallback(async (userId: string): Promise<User | null> => {
    return await fetchUserByIdApi(request, userId);
  }, [request]);

  // Generate edit fields from attributes dynamically
  const generateEditFieldsFromAttributes = useCallback((): Array<{
    key: string;
    label: string;
    type: 'string' | 'boolean' | 'email' | 'textarea' | 'date' | 'enum' | 'multiselect' | 'readonly';
    editable?: boolean;
    required?: boolean;
    validator?: (value: any) => string | null;
    minRows?: number;
    maxRows?: number;
    options?: Array<{ value: string | number; label: string }>;
    optionsReference?: string; // For options that need to be fetched (e.g., "user.role")
  }> => {
    if (!attributes || attributes.length === 0) {
      return [];
    }

    const editableFields = attributes
      .filter(attr => {
        // Filter out non-editable fields based on readonly/editable flags
        if (attr.readonly === true || attr.editable === false) {
          return false; // Don't show readonly fields in edit form
        }
        // Also filter out common non-editable fields
        const nonEditableFields = ['id', 'mandateId', '_createdBy', '_hideDelete'];
        return !nonEditableFields.includes(attr.name);
      })
      .map(attr => {
        // Map backend attribute type to form field type
        let fieldType: 'string' | 'boolean' | 'email' | 'textarea' | 'date' | 'enum' | 'multiselect' | 'readonly' = 'string';
        let options: Array<{ value: string | number; label: string }> | undefined = undefined;
        let optionsReference: string | undefined = undefined;
        
        // Handle readonly fields
        if (attr.readonly === true || attr.editable === false) {
          fieldType = 'readonly';
        }
        // Map backend types to form field types
        else if (attr.type === 'checkbox') {
          fieldType = 'boolean';
        } else if (attr.type === 'email') {
          fieldType = 'email';
        } else if (attr.type === 'date') {
          fieldType = 'date';
        } else if (attr.type === 'select') {
          fieldType = 'enum';
          // Handle options - can be array or string reference
          if (Array.isArray(attr.options)) {
            options = attr.options.map(opt => {
              const labelValue = typeof opt.label === 'string' 
                ? opt.label 
                : opt.label?.en || opt.label?.[Object.keys(opt.label)[0]] || String(opt.value);
              return {
                value: opt.value,
                label: labelValue
              };
            });
          } else if (typeof attr.options === 'string') {
            // Options reference (e.g., "user.role", "auth.authority")
            optionsReference = attr.options;
          }
        } else if (attr.type === 'multiselect') {
          fieldType = 'multiselect';
          // Handle options - can be array or string reference
          if (Array.isArray(attr.options)) {
            options = attr.options.map(opt => {
              const labelValue = typeof opt.label === 'string' 
                ? opt.label 
                : opt.label?.en || opt.label?.[Object.keys(opt.label)[0]] || String(opt.value);
              return {
                value: opt.value,
                label: labelValue
              };
            });
          } else if (typeof attr.options === 'string') {
            // Options reference (e.g., "user.role", "auth.authority")
            optionsReference = attr.options;
          }
        } else if (attr.type === 'textarea') {
          fieldType = 'textarea';
        } else if (attr.type === 'text') {
          // Check if it should be textarea based on name
          if (attr.name.toLowerCase().includes('description') || 
              attr.name.toLowerCase().includes('content') ||
              attr.name.toLowerCase().includes('note')) {
            fieldType = 'textarea';
          } else {
            fieldType = 'string';
          }
        }
        // Note: Legacy 'boolean' and 'enum' types are not in the AttributeDefinition type union
        // If needed, they should be handled via type casting: (attr as any).type === 'boolean'

        // Define validators and required fields
        let required = attr.required === true;
        let validator: ((value: any) => string | null) | undefined = undefined;
        let minRows: number | undefined = undefined;
        let maxRows: number | undefined = undefined;

        // Email validation
        if (fieldType === 'email') {
          validator = (value: any) => {
            if (required && (!value || (typeof value === 'string' && value.trim() === ''))) {
              return 'Email cannot be empty';
            }
            if (value && typeof value === 'string' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
              return 'Invalid email format';
            }
            return null;
          };
        }
        // Textarea settings
        else if (fieldType === 'textarea') {
          minRows = 4;
          maxRows = 8;
          if (attr.name.toLowerCase().includes('content')) {
            minRows = 6;
            maxRows = 12;
          }
        }
        // Multiselect validation
        else if (fieldType === 'multiselect' && required) {
          validator = (value: any[]) => {
            if (!value || !Array.isArray(value) || value.length === 0) {
              return `${attr.label} is required`;
            }
            return null;
          };
        }

        return {
          key: attr.name,
          label: attr.label || attr.name,
          type: fieldType,
          editable: (attr as any).editable !== false && (attr as any).readonly !== true,
          required,
          validator,
          minRows,
          maxRows,
          options,
          optionsReference
        };
      });

    return editableFields;
  }, [attributes]);

  // Generate create fields from attributes dynamically
  // For users, we add a password field that's not in the backend attributes (since passwords are hashed)
  const generateCreateFieldsFromAttributes = useCallback((): Array<{
    key: string;
    label: string;
    type: 'string' | 'boolean' | 'email' | 'textarea' | 'date' | 'enum' | 'multiselect' | 'readonly';
    required?: boolean;
    validator?: (value: any) => string | null;
    minRows?: number;
    maxRows?: number;
    options?: Array<{ value: string | number; label: string }>;
    optionsReference?: string;
    placeholder?: string;
  }> => {
    if (!attributes || attributes.length === 0) {
      return [];
    }

    const createFields = attributes
      .filter(attr => {
        // Filter out non-editable fields and auto-generated fields for create forms
        if (attr.readonly === true || attr.editable === false) {
          return false;
        }
        // Filter out ID fields and other auto-generated fields
        const nonEditableFields = ['id', 'mandateId', '_createdBy', '_hideDelete', 'authenticationAuthority'];
        return !nonEditableFields.includes(attr.name);
      })
      .map(attr => {
        // Map backend attribute type to form field type
        let fieldType: 'string' | 'boolean' | 'email' | 'textarea' | 'date' | 'enum' | 'multiselect' | 'readonly' = 'string';
        let options: Array<{ value: string | number; label: string }> | undefined = undefined;
        let optionsReference: string | undefined = undefined;
        
        // Map backend types to form field types
        // Cast to string to handle all possible backend type values
        const attrType = attr.type as string;
        if (attrType === 'checkbox' || attrType === 'boolean') {
          fieldType = 'boolean';
        } else if (attrType === 'email') {
          fieldType = 'email';
        } else if (attrType === 'timestamp' || attrType === 'date' || attrType === 'time') {
          fieldType = 'date';
        } else if (attrType === 'select' || attrType === 'enum') {
          fieldType = 'enum';
          if (Array.isArray(attr.options)) {
            options = attr.options.map(opt => {
              const labelValue = typeof opt.label === 'string' 
                ? opt.label 
                : opt.label?.en || opt.label?.[Object.keys(opt.label || {})[0]] || String(opt.value);
              return {
                value: opt.value,
                label: labelValue
              };
            });
          } else if (typeof attr.options === 'string') {
            optionsReference = attr.options;
          }
        } else if (attrType === 'multiselect') {
          fieldType = 'multiselect';
          if (Array.isArray(attr.options)) {
            options = attr.options.map(opt => {
              const labelValue = typeof opt.label === 'string' 
                ? opt.label 
                : opt.label?.en || opt.label?.[Object.keys(opt.label || {})[0]] || String(opt.value);
              return {
                value: opt.value,
                label: labelValue
              };
            });
          } else if (typeof attr.options === 'string') {
            optionsReference = attr.options;
          }
        } else if (attrType === 'textarea') {
          fieldType = 'textarea';
        }
        
        // Determine if required and build validator
        const required = attr.required === true;
        let validator: ((value: any) => string | null) | undefined = undefined;
        
        // Email validation
        if (attr.type === 'email') {
          validator = (value: any) => {
            if (required && (!value || (typeof value === 'string' && value.trim() === ''))) {
              return 'Email cannot be empty';
            }
            if (value && typeof value === 'string' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
              return 'Invalid email format';
            }
            return null;
          };
        }
        // Required string validation
        else if (required && fieldType === 'string') {
          validator = (value: any) => {
            if (!value || (typeof value === 'string' && value.trim() === '')) {
              return `${attr.label} is required`;
            }
            return null;
          };
        }
        // Multiselect validation
        else if (fieldType === 'multiselect' && required) {
          validator = (value: any[]) => {
            if (!value || !Array.isArray(value) || value.length === 0) {
              return `${attr.label} is required`;
            }
            return null;
          };
        }

        return {
          key: attr.name,
          label: attr.label || attr.name,
          type: fieldType,
          required,
          validator,
          options,
          optionsReference
        };
      });

    // Note: Password field removed - users are created without password
    // Admin can send password setup link after user creation using handleSendPasswordLink

    return createFields;
  }, [attributes]);

  // Ensure attributes are loaded - can be called by EditActionButton
  const ensureAttributesLoaded = useCallback(async () => {
    // Don't fetch attributes if user is not authenticated (prevents 401 errors)
    const currentUser = getUserDataCache();
    if (!currentUser) {
      return [];
    }
    
    if (attributes && attributes.length > 0) {
      return attributes;
    }
    
    const fetchedAttributes = await fetchAttributes();
    return fetchedAttributes;
  }, [attributes, fetchAttributes]);

  // Fetch attributes and permissions on mount (only if user is authenticated)
  useEffect(() => {
    const currentUser = getUserDataCache();
    if (currentUser) {
      fetchAttributes();
      fetchPermissions();
    }
  }, [fetchAttributes, fetchPermissions]);

  // Initial fetch
  useEffect(() => {
    fetchUsers();
  }, [fetchUsers]);

  return {
    data: users,
    loading,
    error,
    refetch: fetchUsers,
    removeOptimistically,
    updateOptimistically,
    attributes,
    permissions,
    pagination,
    fetchUserById,
    generateEditFieldsFromAttributes,
    generateCreateFieldsFromAttributes,
    ensureAttributesLoaded
  };
}

// User operations hook
export function useUserOperations() {
  const [deletingUsers, setDeletingUsers] = useState<Set<string>>(new Set());
  const [editingUsers, setEditingUsers] = useState<Set<string>>(new Set());
  const [sendingPasswordLink, setSendingPasswordLink] = useState<Set<string>>(new Set());
  const [creatingUser, setCreatingUser] = useState(false);
  const { request, isLoading } = useApiRequest();
  const [deleteError, setDeleteError] = useState<string | null>(null);
  const [createError, setCreateError] = useState<string | null>(null);
  const [updateError, setUpdateError] = useState<string | null>(null);
  const [passwordLinkError, setPasswordLinkError] = useState<string | null>(null);

  const handleUserDelete = async (userId: string) => {
    setDeleteError(null);
    setDeletingUsers(prev => new Set(prev).add(userId));
    
    try {
      await deleteUserApi(request, userId);
      
      await new Promise(resolve => setTimeout(resolve, 300));
      return true;
    } catch (error: any) {
      setDeleteError(error.message);
      return false;
    } finally {
      setDeletingUsers(prev => {
        const newSet = new Set(prev);
        newSet.delete(userId);
        return newSet;
      });
    }
  };

  const handleUserCreate = async (userData: Omit<User, 'id'>) => {
    setCreateError(null);
    setCreatingUser(true);
    
    try {
      // mandateId wird nicht mehr vom Client gesendet
      // Das Backend bestimmt den Kontext über die instanceId im Request
      const newUser = await createUserApi(request, userData);
      
      return { success: true, userData: newUser };
    } catch (error: any) {
      setCreateError(error.message);
      return { success: false, error: error.message };
    } finally {
      setCreatingUser(false);
    }
  };

  // Send password setup link to a user (admin function)
  const handleSendPasswordLink = async (userId: string) => {
    setPasswordLinkError(null);
    setSendingPasswordLink(prev => new Set(prev).add(userId));
    
    try {
      // Get frontend URL from current window location
      const frontendUrl = `${window.location.protocol}//${window.location.host}`;
      
      const result = await sendPasswordLinkApi(request, userId, frontendUrl);
      
      return { success: true, message: result.message, email: result.email };
    } catch (error: any) {
      const errorMessage = error.response?.data?.detail || error.message || 'Failed to send password link';
      setPasswordLinkError(errorMessage);
      return { success: false, error: errorMessage };
    } finally {
      setSendingPasswordLink(prev => {
        const newSet = new Set(prev);
        newSet.delete(userId);
        return newSet;
      });
    }
  };

  const handleUserUpdate = async (userId: string, updateData: UserUpdateData, _originalData?: any) => {
    setUpdateError(null);
    setEditingUsers(prev => new Set(prev).add(userId));
    
    try {
      // mandateId wird nicht mehr vom Client gesendet
      const updatedUser = await updateUserApi(request, userId, updateData);
      
      return { success: true, userData: updatedUser };
    } catch (error: any) {
      const errorMessage = error.response?.data?.message || error.message || 'Failed to update user';
      const statusCode = error.response?.status;
      
      setUpdateError(errorMessage);
      
      return { 
        success: false, 
        error: errorMessage,
        statusCode,
        isPermissionError: statusCode === 403,
        isValidationError: statusCode === 400
      };
    } finally {
      setEditingUsers(prev => {
        const newSet = new Set(prev);
        newSet.delete(userId);
        return newSet;
      });
    }
  };

  // Generic inline update handler for FormGeneratorTable
  // Must merge changes with existing row data because backend requires full object
  // The existingRow parameter is passed from FormGeneratorTable which has access to row data
  const handleInlineUpdate = async (userId: string, changes: Partial<UserUpdateData>, existingRow?: any) => {
    if (!existingRow) {
      throw new Error(`Existing row data required for inline update`);
    }
    
    // Merge changes with existing row data (backend requires full object with required fields)
    const mergedData: UserUpdateData = {
      username: existingRow.username,
      email: existingRow.email,
      enabled: existingRow.enabled,
      roleLabels: existingRow.roleLabels,
      ...changes
    };
    
    const result = await handleUserUpdate(userId, mergedData);
    if (!result.success) {
      throw new Error(result.error || 'Failed to update');
    }
    return result;
  };

  return {
    deletingUsers,
    editingUsers,
    sendingPasswordLink,
    creatingUser,
    deleteError,
    createError,
    updateError,
    passwordLinkError,
    handleUserDelete,
    handleUserCreate,
    handleUserUpdate,
    handleInlineUpdate,
    handleSendPasswordLink,
    isLoading
  };
}

// Individual user operations hook (for use when you don't need the full list)
export function useUser() {
  const { request, isLoading, error } = useApiRequest();

  const getUser = async (userId: string): Promise<User> => {
    const user = await fetchUserByIdApi(request, userId);
    if (!user) {
      throw new Error('User not found');
    }
    return user;
  };

  const updateUser = async (userId: string, userData: UserUpdateData): Promise<User> => {
    return await updateUserApi(request, userId, userData);
  };

  const deleteUser = async (userId: string): Promise<void> => {
    await deleteUserApi(request, userId);
  };

  return {
    getUser,
    updateUser,
    deleteUser,
    isLoading,
    error
  };
} 