import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
import { GLOBAL_USER_ROLES, type GlobalUserRole } from '../types/roles';

export interface User {
  id: string;
  email: string;
  full_name: string;  // Updated to match backend
  is_active: boolean;
  is_verified: boolean;
  created_at: string;
  last_login?: string;
  phone?: string;
  language?: string;
  timezone?: string;
  tenant_id?: string;
  role?: GlobalUserRole;
}

export interface AuthState {
  // State
  user: User | null;
  token: string | null;
  refreshToken: string | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  error: string | null;
  
  // Actions
  login: (email: string, password: string) => Promise<void>;
  register: (userData: { email: string; password: string; full_name: string; tenant_name?: string }) => Promise<void>;
  logout: () => void;
  refreshAuth: () => Promise<void>;
  updateUser: (updates: Partial<User>) => void;
  clearError: () => void;
  setLoading: (loading: boolean) => void;
  
  // Permission helpers
  hasPermission: (permission: string) => boolean;
  hasRole: (role: string) => boolean;
  canAccess: (resource: string, action: string) => boolean;
}

import { authService, apiClient } from '../api';

export const useAuthStore = create<AuthState>()(
  persist(
    (set, get) => ({
      // Initial state
      user: null,
      token: null,
      refreshToken: null,
      isAuthenticated: false,
      isLoading: false,
      error: null,

      // Actions
      login: async (email: string, password: string) => {
        try {
          set({ isLoading: true, error: null });

          const response = await authService.login({ email, password });

          if (response && response.access_token) {
            // Set the auth tokens on the API client immediately
            apiClient.setAuthToken(response.access_token);
            if (response.refresh_token) {
              apiClient.setRefreshToken(response.refresh_token);
            }

            set({
              user: response.user || null,
              token: response.access_token,
              refreshToken: response.refresh_token || null,
              isAuthenticated: true,
              isLoading: false,
              error: null,
            });
          } else {
            throw new Error('Login failed');
          }
        } catch (error) {
          set({
            user: null,
            token: null,
            refreshToken: null,
            isAuthenticated: false,
            isLoading: false,
            error: error instanceof Error ? error.message : 'Error de autenticación',
          });
          throw error;
        }
      },

      register: async (userData: { email: string; password: string; full_name: string; tenant_name?: string }) => {
        try {
          set({ isLoading: true, error: null });

          const response = await authService.register(userData);

          if (response && response.access_token) {
            // Set the auth tokens on the API client immediately
            apiClient.setAuthToken(response.access_token);
            if (response.refresh_token) {
              apiClient.setRefreshToken(response.refresh_token);
            }

            set({
              user: response.user || null,
              token: response.access_token,
              refreshToken: response.refresh_token || null,
              isAuthenticated: true,
              isLoading: false,
              error: null,
            });
          } else {
            throw new Error('Registration failed');
          }
        } catch (error) {
          set({
            user: null,
            token: null,
            refreshToken: null,
            isAuthenticated: false,
            isLoading: false,
            error: error instanceof Error ? error.message : 'Error de registro',
          });
          throw error;
        }
      },

      logout: () => {
        // Clear the auth tokens from API client
        apiClient.setAuthToken(null);
        apiClient.setRefreshToken(null);
        apiClient.setTenantId(null);

        set({
          user: null,
          token: null,
          refreshToken: null,
          isAuthenticated: false,
          isLoading: false,
          error: null,
        });
      },

      refreshAuth: async () => {
        try {
          const { refreshToken } = get();
          if (!refreshToken) {
            throw new Error('No refresh token available');
          }

          set({ isLoading: true });
          
          const response = await authService.refreshToken(refreshToken);
          
          if (response && response.access_token) {
            // Set the auth tokens on the API client immediately
            apiClient.setAuthToken(response.access_token);
            if (response.refresh_token) {
              apiClient.setRefreshToken(response.refresh_token);
            }

            set({
              token: response.access_token,
              refreshToken: response.refresh_token || refreshToken,
              isLoading: false,
              error: null,
            });
          } else {
            throw new Error('Token refresh failed');
          }
        } catch (error) {
          set({
            user: null,
            token: null,
            refreshToken: null,
            isAuthenticated: false,
            isLoading: false,
            error: error instanceof Error ? error.message : 'Error al renovar sesión',
          });
          throw error;
        }
      },

      updateUser: (updates: Partial<User>) => {
        const { user } = get();
        if (user) {
          set({
            user: { ...user, ...updates },
          });
        }
      },

      clearError: () => {
        set({ error: null });
      },

      setLoading: (loading: boolean) => {
        set({ isLoading: loading });
      },

      // Permission helpers - Global user permissions only
      hasPermission: (_permission: string): boolean => {
        const { user } = get();
        if (!user || !user.is_active) return false;
        
        // Super admin and admin have all global permissions
        if (user.role === GLOBAL_USER_ROLES.SUPER_ADMIN || user.role === GLOBAL_USER_ROLES.ADMIN) {
          return true;
        }
        
        // Manager has limited permissions
        if (user.role === GLOBAL_USER_ROLES.MANAGER) {
          return ['user_management', 'system_settings'].includes(_permission);
        }
        
        // Regular users have basic permissions
        return false;
      },

      hasRole: (role: string): boolean => {
        const { user } = get();
        return user?.role === role;
      },

      canAccess: (resource: string, action: string): boolean => {
        const { user } = get();
        if (!user || !user.is_active) return false;
        
        // Global role-based access control (system-wide)
        switch (user.role) {
          case GLOBAL_USER_ROLES.SUPER_ADMIN:
          case GLOBAL_USER_ROLES.ADMIN:
            return true;
          case GLOBAL_USER_ROLES.MANAGER:
            return ['users', 'system'].includes(resource);
          case GLOBAL_USER_ROLES.USER:
            return action === 'read';
          default:
            return false;
        }
      },
    }),
    {
      name: 'auth-storage',
      storage: createJSONStorage(() => localStorage),
      partialize: (state) => ({
        user: state.user,
        token: state.token,
        refreshToken: state.refreshToken,
        isAuthenticated: state.isAuthenticated,
      }),
      onRehydrateStorage: () => (state) => {
        // Initialize API client with stored tokens when store rehydrates
        if (state?.token) {
          // Use direct import to avoid timing issues
          apiClient.setAuthToken(state.token);
          if (state.refreshToken) {
            apiClient.setRefreshToken(state.refreshToken);
          }

          if (state.user?.tenant_id) {
            apiClient.setTenantId(state.user.tenant_id);
          }
        }
      },
    }
  )
);

// Selectors for common use cases
export const useAuthUser = () => useAuthStore((state) => state.user);
export const useIsAuthenticated = () => useAuthStore((state) => state.isAuthenticated);
export const useAuthLoading = () => useAuthStore((state) => state.isLoading);
export const useAuthError = () => useAuthStore((state) => state.error);
export const usePermissions = () => useAuthStore((state) => ({
  hasPermission: state.hasPermission,
  hasRole: state.hasRole,
  canAccess: state.canAccess,
}));

// Hook for auth actions
export const useAuthActions = () => useAuthStore((state) => ({
  login: state.login,
  register: state.register,
  logout: state.logout,
  refreshAuth: state.refreshAuth,
  updateUser: state.updateUser,
  clearError: state.clearError,
  setLoading: state.setLoading,
}));