import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
import { GLOBAL_USER_ROLES, type GlobalUserRole } from '../types/roles';
import { getSubscriptionFromJWT, getTenantAccessFromJWT, getPrimaryTenantIdFromJWT, JWTSubscription } from '../utils/jwt';
import { JWTSubscription as JWTSubscriptionType } from '../utils/jwt';

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;
  avatar?: string; // User avatar image URL
  tenant_id?: string | null;
  role?: GlobalUserRole;
}

export interface AuthState {
  // State
  user: User | null;
  token: string | null;
  refreshToken: string | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  error: string | null;
  jwtSubscription: JWTSubscription | null;
  jwtTenantAccess: Array<{
    id: string;
    role: string;
    tier: string;
  }> | null;
  primaryTenantId: string | null;
  subscription_from_jwt?: boolean;
  pendingSubscriptionId?: string | null;  // Subscription ID from registration (before tenant creation)

  // Actions
  login: (email: string, password: string) => Promise<void>;
  

  
  logout: () => void;
  refreshAuth: () => Promise<void>;
  updateUser: (updates: Partial<User>) => void;
  clearError: () => void;
  setLoading: (loading: boolean) => void;
  setDemoAuth: (token: string, demoUser: Partial<User>, subscriptionTier?: string) => void;
  setPendingSubscriptionId: (subscriptionId: string | null) => void;  // Store subscription ID from registration

  // Registration Flow - Atomic Registration with 3DS Support
  createRegistrationPaymentSetup: (registrationData: {
    email: string;
    full_name: string;
    password: string;
    subscription_plan: string;
    billing_cycle: string;
    payment_method_id: string;
    coupon_code?: string;
    terms_accepted: boolean;
    privacy_accepted: boolean;
    marketing_consent: boolean;
    analytics_consent: boolean;
  }) => Promise<any>;

  verifySetupIntent: (setupIntentId: string) => Promise<any>;

  completeRegistrationAfterPayment: (registrationData: {
    email: string;
    full_name: string;
    password: string;
    subscription_plan: string;
    billing_cycle: string;
    payment_customer_id: string;
    payment_method_id: string;
    subscription_id: string;
    coupon_code?: string;
    terms_accepted: boolean;
    privacy_accepted: boolean;
    marketing_consent: boolean;
    analytics_consent: boolean;
    threeds_completed: boolean;
    setup_intent_id: string;
  }) => Promise<any>;

  // 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,
      jwtSubscription: null,
      jwtTenantAccess: null,
      primaryTenantId: null,
      pendingSubscriptionId: 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);
            }

            // NEW: Extract subscription from JWT
            const jwtSubscription = getSubscriptionFromJWT(response.access_token);
            const jwtTenantAccess = getTenantAccessFromJWT(response.access_token);
            const primaryTenantId = getPrimaryTenantIdFromJWT(response.access_token);

            set({
              user: response.user || null,
              token: response.access_token,
              refreshToken: response.refresh_token || null,
              isAuthenticated: true,
              isLoading: false,
              error: null,
              jwtSubscription,
              jwtTenantAccess,
              primaryTenantId,
            });
          } 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;
        }
      },

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

        // Clear tenant store to remove cached tenant data
        // Import dynamically to avoid circular dependencies
        import('./tenant.store').then(({ useTenantStore }) => {
          useTenantStore.getState().clearTenants();
        }).catch(err => {
          console.warn('Failed to clear tenant store on logout:', err);
        });

        // Note: Notification storage is now handled by React Query cache
        // which is cleared automatically on logout

        set({
          user: null,
          token: null,
          refreshToken: null,
          isAuthenticated: false,
          isLoading: false,
          error: null,
          jwtSubscription: null,
          jwtTenantAccess: null,
          primaryTenantId: null,
          pendingSubscriptionId: 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);
            }

            // NEW: Extract FRESH subscription from new JWT
            const jwtSubscription = getSubscriptionFromJWT(response.access_token);
            const jwtTenantAccess = getTenantAccessFromJWT(response.access_token);
            const primaryTenantId = getPrimaryTenantIdFromJWT(response.access_token);

            set({
              token: response.access_token,
              refreshToken: response.refresh_token || refreshToken,
              isLoading: false,
              error: null,
              // NEW: Update subscription from fresh JWT
              jwtSubscription,
              jwtTenantAccess,
              primaryTenantId,
            });

            console.log('Auth refreshed with new subscription:', jwtSubscription?.tier);
          } else {
            throw new Error('Token refresh failed');
          }
        } catch (error) {
          // CRITICAL: Only reset isLoading, don't log out the user
          // The user's session is still valid even if token refresh fails
          // They can continue using the app with their current token
          set({
            isLoading: false,
            error: error instanceof Error ? error.message : 'Error al renovar sesión',
          });

          console.error('Token refresh failed but keeping user logged in:', error);
          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 });
      },

      setPendingSubscriptionId: (subscriptionId: string | null) => {
        set({ pendingSubscriptionId: subscriptionId });
      },

      setDemoAuth: (token: string, demoUser: Partial<User>, subscriptionTier?: string) => {
        console.log('🔧 [Auth Store] setDemoAuth called - demo sessions use X-Demo-Session-Id header, not JWT');
        // DO NOT set API client token for demo sessions!
        // Demo authentication works via X-Demo-Session-Id header, not JWT
        // The demo middleware handles authentication server-side

        // NEW: Create synthetic JWT subscription data for demo sessions
        const jwtSubscription = subscriptionTier ? {
          tier: subscriptionTier as 'starter' | 'professional' | 'enterprise',
          status: 'active' as const,
          valid_until: null
        } : null;

        // Update store state so user is marked as authenticated
        set({
          token: null, // No JWT token for demo sessions
          refreshToken: null,
          user: demoUser as User,
          isAuthenticated: true, // User is authenticated via demo session
          isLoading: false,
          error: null,
          jwtSubscription,  // NEW: Set subscription data for demo sessions
          subscription_from_jwt: true,  // NEW: Flag to indicate subscription is from JWT
        });
        console.log('✅ [Auth Store] Demo auth state updated (no JWT token)', { subscriptionTier });
      },

      // ===================================================================
      // REGISTRATION FLOW - Atomic Registration with 3DS Support
      // ===================================================================

      /**
       * Create registration payment setup (Step 1 of atomic registration)
       * This initiates the SetupIntent-first registration flow
       */
      createRegistrationPaymentSetup: async (registrationData: {
        email: string;
        full_name: string;
        password: string;
        subscription_plan: string;
        billing_cycle: string;
        payment_method_id: string;
        coupon_code?: string;
        terms_accepted: boolean;
        privacy_accepted: boolean;
        marketing_consent: boolean;
        analytics_consent: boolean;
      }) => {
        try {
          set({ isLoading: true, error: null });

          // Map frontend data to backend UserRegistration schema
          const userData: any = {
            email: registrationData.email,
            password: registrationData.password,
            full_name: registrationData.full_name,
            subscription_plan: registrationData.subscription_plan,
            billing_cycle: registrationData.billing_cycle,
            payment_method_id: registrationData.payment_method_id,
            coupon_code: registrationData.coupon_code,
            terms_accepted: registrationData.terms_accepted,
            privacy_accepted: registrationData.privacy_accepted,
            marketing_consent: registrationData.marketing_consent,
            analytics_consent: registrationData.analytics_consent,
          };

          // Call the auth service to start registration
          const response = await authService.startRegistration(userData);

          if (response.requires_action) {
            // 3DS required - return SetupIntent data for frontend handling
            return {
              requires_action: true,
              action_type: response.action_type,
              client_secret: response.client_secret,
              setup_intent_id: response.setup_intent_id,
              customer_id: response.customer_id,
              payment_customer_id: response.payment_customer_id,
              plan_id: response.plan_id,
              payment_method_id: response.payment_method_id,
              billing_cycle: response.billing_cycle,
              email: response.email,
            };
          } else {
            // No 3DS required - registration completed immediately
            if (response.user) {
              // Set the auth tokens on the API client
              if (response.access_token) {
                apiClient.setAuthToken(response.access_token);
              }
              if (response.refresh_token) {
                apiClient.setRefreshToken(response.refresh_token);
              }

              // Extract subscription from JWT if available
              const jwtSubscription = response.access_token ? getSubscriptionFromJWT(response.access_token) : null;
              const jwtTenantAccess = response.access_token ? getTenantAccessFromJWT(response.access_token) : null;
              const primaryTenantId = response.access_token ? getPrimaryTenantIdFromJWT(response.access_token) : null;

              set({
                user: {
                  id: response.user.id,
                  email: response.user.email,
                  full_name: response.user.full_name,
                  is_active: response.user.is_active,
                  is_verified: response.user.is_verified,
                  created_at: response.user.created_at,
                  tenant_id: response.user.tenant_id,
                  role: response.user.role,
                },
                token: response.access_token || null,
                refreshToken: response.refresh_token || null,
                isAuthenticated: true,
                isLoading: false,
                error: null,
                jwtSubscription,
                jwtTenantAccess,
                primaryTenantId,
                pendingSubscriptionId: response.subscription_id || null,
              });

              return {
                success: true,
                requires_action: false,
                user: response.user,
                subscription_id: response.subscription_id,
                payment_customer_id: response.payment_customer_id,
                message: response.message,
              };
            }
          }

          return response;
        } catch (error) {
          set({
            isLoading: false,
            error: error instanceof Error ? error.message : 'Registration setup failed',
          });
          throw error;
        }
      },

      /**
       * Verify SetupIntent status (optional step in registration flow)
       */
      verifySetupIntent: async (setupIntentId: string) => {
        try {
          set({ isLoading: true, error: null });

          // This would call a backend endpoint to verify SetupIntent status
          // For now, we'll return a mock response
          return {
            status: 'succeeded',
            setup_intent_id: setupIntentId,
            requires_action: false,
          };
        } catch (error) {
          set({
            isLoading: false,
            error: error instanceof Error ? error.message : 'SetupIntent verification failed',
          });
          throw error;
        }
      },

      /**
       * Complete registration after payment verification (Step 2 of atomic registration)
       * This is called after frontend confirms SetupIntent and handles 3DS
       */
      completeRegistrationAfterPayment: async (registrationData: {
        email: string;
        full_name: string;
        password: string;
        subscription_plan: string;
        billing_cycle: string;
        payment_customer_id: string;
        payment_method_id: string;
        subscription_id: string;
        coupon_code?: string;
        terms_accepted: boolean;
        privacy_accepted: boolean;
        marketing_consent: boolean;
        analytics_consent: boolean;
        threeds_completed: boolean;
        setup_intent_id: string;
      }) => {
        try {
          set({ isLoading: true, error: null });

          // Prepare verification data for backend
          const verificationData = {
            setup_intent_id: registrationData.setup_intent_id,
            user_data: {
              email: registrationData.email,
              password: registrationData.password,
              full_name: registrationData.full_name,
              subscription_plan: registrationData.subscription_plan,
              billing_cycle: registrationData.billing_cycle,
              payment_method_id: registrationData.payment_method_id,
              coupon_code: registrationData.coupon_code,
              terms_accepted: registrationData.terms_accepted,
              privacy_accepted: registrationData.privacy_accepted,
              marketing_consent: registrationData.marketing_consent,
              analytics_consent: registrationData.analytics_consent,
            },
          };

          // Call the auth service to complete registration
          const response = await authService.completeRegistration(verificationData);

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

            // Extract subscription from JWT if available
            const jwtSubscription = response.access_token ? getSubscriptionFromJWT(response.access_token) : null;
            const jwtTenantAccess = response.access_token ? getTenantAccessFromJWT(response.access_token) : null;
            const primaryTenantId = response.access_token ? getPrimaryTenantIdFromJWT(response.access_token) : null;

            set({
              user: {
                id: response.user.id,
                email: response.user.email,
                full_name: response.user.full_name,
                is_active: response.user.is_active,
                is_verified: response.user.is_verified,
                created_at: response.user.created_at,
                tenant_id: response.user.tenant_id,
                role: response.user.role,
              },
              token: response.access_token || null,
              refreshToken: response.refresh_token || null,
              isAuthenticated: true,
              isLoading: false,
              error: null,
              jwtSubscription,
              jwtTenantAccess,
              primaryTenantId,
              pendingSubscriptionId: response.subscription_id || null,
            });

            return {
              success: true,
              user: response.user,
              subscription_id: response.subscription_id,
              payment_customer_id: response.payment_customer_id,
              message: response.message,
              access_token: response.access_token,
              refresh_token: response.refresh_token,
            };
          }

          return {
            success: false,
            message: response.message || 'Registration completion failed',
          };
        } catch (error) {
          set({
            isLoading: false,
            error: error instanceof Error ? error.message : 'Registration completion failed',
          });
          throw error;
        }
      },

      // 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,
        // CRITICAL: Persist JWT subscription data for UI consistency
        jwtSubscription: state.jwtSubscription,
        jwtTenantAccess: state.jwtTenantAccess,
        primaryTenantId: state.primaryTenantId,
      }),
      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 useJWTSubscription = () => useAuthStore((state) => state.jwtSubscription);
export const useJWTTenantAccess = () => useAuthStore((state) => state.jwtTenantAccess);
export const usePrimaryTenantId = () => useAuthStore((state) => state.primaryTenantId);
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,
  logout: state.logout,
  refreshAuth: state.refreshAuth,
  updateUser: state.updateUser,
  clearError: state.clearError,
  setLoading: state.setLoading,
}));