import { create } from 'zustand'
import { persist } from 'zustand/middleware'
import type { User, Token, UserCreate, UserLogin, Account, SubscriptionDetails } from '@/types'
import { authApi } from '@/api/auth'
import { apiClient } from '@/api/client'
import { clearCachedQuota } from '@/hooks/useCachedQuota'

interface AuthState {
  user: User | null
  token: Token | null
  account: Account | null
  subscription: SubscriptionDetails | null
  isAuthenticated: boolean
  isLoading: boolean
  error: string | null

  // Actions
  login: (credentials: UserLogin) => Promise<void>
  register: (data: UserCreate) => Promise<void>
  logout: () => Promise<void>
  fetchUser: () => Promise<void>
  setTokens: (token: Token) => void
  clearError: () => void
  setLoading: (loading: boolean) => void
}

export const useAuthStore = create<AuthState>()(
  persist(
    (set, get) => ({
      user: null,
      token: null,
      account: null,
      subscription: null,
      isAuthenticated: false,
      isLoading: false,
      error: null,

      login: async (credentials: UserLogin) => {
        set({ isLoading: true, error: null })
        try {
          const token = await authApi.login(credentials)

          // Store tokens
          localStorage.setItem('access_token', token.access_token)
          localStorage.setItem('refresh_token', token.refresh_token)

          set({ token, isAuthenticated: true })

          // Fetch user info
          await get().fetchUser()
        } catch (error: unknown) {
          const axiosErr = error as { response?: { data?: { detail?: unknown } } }
          const rawDetail = axiosErr.response?.data?.detail
          const message = (typeof rawDetail === 'string' ? rawDetail : null) || (error instanceof Error ? error.message : 'Login failed')
          set({ error: message, isLoading: false })
          throw error
        }
      },

      register: async (data: UserCreate) => {
        set({ isLoading: true, error: null })
        try {
          await authApi.register(data)
          // After registration, log the user in
          await get().login({ email: data.email, password: data.password })
        } catch (error: unknown) {
          const axiosErr = error as { response?: { data?: { detail?: unknown } } }
          const rawDetail = axiosErr.response?.data?.detail
          const message = (typeof rawDetail === 'string' ? rawDetail : null) || (error instanceof Error ? error.message : 'Registration failed')
          set({ error: message, isLoading: false })
          throw error
        }
      },

      logout: async () => {
        try {
          await authApi.logout()
        } catch {
          // Ignore logout errors
        } finally {
          localStorage.removeItem('access_token')
          localStorage.removeItem('refresh_token')
          clearCachedQuota()
          set({ user: null, token: null, account: null, subscription: null, isAuthenticated: false, error: null })
        }
      },

      fetchUser: async () => {
        set({ isLoading: true })
        try {
          const [userResult, accountResult, subscriptionResult] = await Promise.allSettled([
            authApi.me(),
            apiClient.get<Account>('/accounts/me').then(r => r.data),
            apiClient.get<SubscriptionDetails>('/accounts/me/subscription').then(r => r.data),
          ])

          const user = userResult.status === 'fulfilled' ? userResult.value : null
          const account = accountResult.status === 'fulfilled' ? accountResult.value : null
          const subscription = subscriptionResult.status === 'fulfilled' ? subscriptionResult.value : null

          if (!user) {
            // User fetch failed — propagate the error
            const reason = userResult.status === 'rejected' ? userResult.reason : new Error('Failed to fetch user')
            throw reason
          }

          set({ user, account, subscription, isLoading: false })
        } catch (error: unknown) {
          const message = error instanceof Error ? error.message : 'Failed to fetch user'
          set({ error: message, isLoading: false })
          throw error
        }
      },

      setTokens: (token: Token) => set({ token }),
      clearError: () => set({ error: null }),
      setLoading: (loading: boolean) => set({ isLoading: loading }),
    }),
    {
      name: 'auth-storage',
      partialize: (state) => ({
        token: state.token,
        isAuthenticated: state.isAuthenticated,
        account: state.account,
        subscription: state.subscription,
      }),
    }
  )
)

export default useAuthStore
