import { create } from 'zustand';
import { persist, devtools } from 'zustand/middleware';
import { login as loginService, register as registerService, logout as logoutService, getMe, type LoginRequest, type RegisterRequest } from '@/services/api/auth';
import { TokenStorage } from '@/services/tokenStorage';
import { csrfService } from '@/services/csrf';
import { broadcastSync } from '@/utils/broadcastSync';
import type { User } from '@/types';
import type { ApiError } from '@/types/api';

// FE-TYPE-011: Fully typed store interfaces
export interface AuthState {
  user: User | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  error: ApiError | null;
}

export interface AuthActions {
  login: (credentials: LoginRequest) => Promise<void>;
  register: (userData: RegisterRequest) => Promise<void>;
  logout: () => Promise<void>;
  refreshUser: () => Promise<void>;
  clearError: () => void;
  setLoading: (loading: boolean) => void;
  checkAuthStatus: () => Promise<void>;
}

// FE-TYPE-011: Export store type for reuse
export type AuthStore = AuthState & AuthActions;

export const useAuthStore = create<AuthStore>()(
  devtools(
    persist(
      broadcastSync(
        (set) => ({
      // État initial
      user: null,
      isAuthenticated: false,
      isLoading: false,
      error: null,

      // Actions
      login: async (credentials: LoginRequest) => {
        set({ isLoading: true, error: null });
        try {
          // Le service auth gère déjà le stockage des tokens
          const response = await loginService(credentials);

          set({
            user: response.user,
            isAuthenticated: true,
            isLoading: false,
            error: null,
          });

          // Récupérer le token CSRF après login
          csrfService.refreshToken().catch((error) => {
            console.warn('Failed to fetch CSRF token after login:', error);
          });
        } catch (error: any) {
          set({
            error: error as ApiError,
            isLoading: false,
            isAuthenticated: false,
            user: null,
          });
          throw error;
        }
      },

      register: async (userData: RegisterRequest) => {
        set({ isLoading: true, error: null });
        try {
          // Le service auth gère déjà le stockage des tokens
          const response = await registerService(userData);

          const isAuth = !!response.access_token;

          set({
            user: response.user,
            isAuthenticated: isAuth,
            isLoading: false,
            error: null,
          });

          // Récupérer le token CSRF après register
          if (isAuth) {
            csrfService.refreshToken().catch((error) => {
              console.warn('Failed to fetch CSRF token after register:', error);
            });
          }
        } catch (error: any) {
          set({
            error: error as ApiError,
            isLoading: false,
            isAuthenticated: false,
            user: null,
          });
          throw error;
        }
      },

      logout: async () => {
        set({ isLoading: true });
        try {
          // Le service auth gère déjà le nettoyage des tokens
          await logoutService();
        } catch (error) {
          console.error('Logout error:', error);
        } finally {
          // INT-016: Le cleanup du refresh proactif est géré par logoutService
          // S'assurer que l'état est nettoyé même en cas d'erreur
          set({
            user: null,
            isAuthenticated: false,
            isLoading: false,
            error: null,
          });

          // Supprimer le token CSRF après logout
          csrfService.clearToken();
        }
      },

      refreshUser: async () => {
        if (!TokenStorage.hasTokens()) {
          set({ user: null, isAuthenticated: false });
          return;
        }

        set({ isLoading: true });
        try {
          const user = await getMe();
          set({
            user,
            isAuthenticated: true,
            isLoading: false,
            error: null,
          });

          // Récupérer le token CSRF après refresh user
          csrfService.refreshToken().catch((error) => {
            console.warn('Failed to fetch CSRF token after refresh user:', error);
          });
        } catch (error: any) {
          // Si l'erreur est 401, le client API gère déjà le refresh automatiquement
          // On nettoie simplement l'état si le refresh échoue
          if (error.code === 401 || error.code === 1001 || error.code === 1002) {
            TokenStorage.clearTokens();
          }

          set({
            error: error as ApiError,
            isLoading: false,
            isAuthenticated: false,
            user: null,
          });
        }
      },

      checkAuthStatus: async () => {
        if (!TokenStorage.hasTokens()) {
          set({ user: null, isAuthenticated: false, isLoading: false });
          return;
        }

        set({ isLoading: true });
        try {
          const user = await getMe();
          set({
            user,
            isAuthenticated: true,
            isLoading: false,
            error: null,
          });

          // INT-016: Initialiser le refresh proactif après vérification du statut
          const { initializeProactiveRefresh } = await import('../services/tokenRefresh');
          initializeProactiveRefresh();

          // Récupérer le token CSRF après check auth status
          csrfService.refreshToken().catch((error) => {
            console.warn('Failed to fetch CSRF token after check auth status:', error);
          });
        } catch (error: any) {
          // Si l'erreur est 401, nettoyer l'état d'authentification
          if (error.code === 401 || error.code === 1001 || error.code === 1002) {
            TokenStorage.clearTokens();
            set({
              user: null,
              isAuthenticated: false,
              isLoading: false,
              error: null,
            });
          } else {
            set({
              error: error as ApiError,
              isLoading: false,
              isAuthenticated: false,
              user: null,
            });
          }
        }
      },

      clearError: () => set({ error: null }),
      setLoading: (loading: boolean) => set({ isLoading: loading }),
      }),
      {
        channelName: 'auth-store',
        enabled: true,
        // FE-STATE-002: Sync user and authentication state across tabs
        shouldSync: (state, prevState) => {
          // Only sync if user or authentication status changed
          return (
            state.user !== prevState?.user ||
            state.isAuthenticated !== prevState?.isAuthenticated
          );
        },
        },
      ),
      {
        name: 'auth-storage',
        partialize: (state) => ({
          user: state.user,
          isAuthenticated: state.isAuthenticated,
          // Note: Les tokens sont stockés dans TokenStorage (localStorage direct)
          // mais on peut aussi les stocker dans le store pour compatibilité
          // Le store Zustand stocke seulement user et isAuthenticated pour éviter la duplication
        }),
      },
    ),
    {
      // FE-STATE-007: Enable Redux DevTools for debugging
      name: 'AuthStore',
      enabled: import.meta.env.DEV,
    },
  ),
);
