/**
 * Authentication Store
 *
 * Manages user authentication state, Discord OAuth flow, and JWT tokens.
 * Persists auth state to localStorage for session persistence.
 */

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { DiscordUser, Team } from '~/types'

export const useAuthStore = defineStore('auth', () => {
  // ============================================================================
  // State
  // ============================================================================

  const token = ref<string | null>(null)
  const refreshToken = ref<string | null>(null)
  const tokenExpiresAt = ref<number | null>(null)
  const user = ref<DiscordUser | null>(null)
  const teams = ref<Team[]>([])
  const isLoading = ref(false)
  const error = ref<string | null>(null)

  // ============================================================================
  // Getters
  // ============================================================================

  const isAuthenticated = computed(() => {
    return token.value !== null && user.value !== null
  })

  const isTokenValid = computed(() => {
    if (!tokenExpiresAt.value) return false
    return Date.now() < tokenExpiresAt.value
  })

  const needsRefresh = computed(() => {
    if (!tokenExpiresAt.value) return false
    // Refresh if token expires in less than 5 minutes
    return Date.now() > tokenExpiresAt.value - 5 * 60 * 1000
  })

  const currentUser = computed(() => user.value)
  const userTeams = computed(() => teams.value)
  const userId = computed(() => user.value?.id ?? null)

  // ============================================================================
  // Actions
  // ============================================================================

  /**
   * Initialize auth state from localStorage
   */
  function initializeAuth() {
    if (process.client) {
      const storedToken = localStorage.getItem('auth_token')
      const storedRefreshToken = localStorage.getItem('refresh_token')
      const storedExpiresAt = localStorage.getItem('token_expires_at')
      const storedUser = localStorage.getItem('user')
      const storedTeams = localStorage.getItem('teams')

      if (storedToken) token.value = storedToken
      if (storedRefreshToken) refreshToken.value = storedRefreshToken
      if (storedExpiresAt) tokenExpiresAt.value = parseInt(storedExpiresAt)
      if (storedUser) user.value = JSON.parse(storedUser)
      if (storedTeams) teams.value = JSON.parse(storedTeams)

      // Check if token needs refresh
      if (needsRefresh.value && refreshToken.value) {
        refreshAccessToken()
      }
    }
  }

  /**
   * Set authentication data after successful login
   */
  function setAuth(data: {
    access_token: string
    refresh_token: string
    expires_in: number
    user: DiscordUser
    teams?: Team[]
  }) {
    token.value = data.access_token
    refreshToken.value = data.refresh_token
    tokenExpiresAt.value = Date.now() + data.expires_in * 1000
    user.value = data.user
    if (data.teams) teams.value = data.teams

    // Persist to localStorage
    if (process.client) {
      localStorage.setItem('auth_token', data.access_token)
      localStorage.setItem('refresh_token', data.refresh_token)
      localStorage.setItem('token_expires_at', tokenExpiresAt.value.toString())
      localStorage.setItem('user', JSON.stringify(data.user))
      if (data.teams) localStorage.setItem('teams', JSON.stringify(data.teams))
    }

    error.value = null
  }

  /**
   * Set user teams (loaded separately from login)
   */
  function setTeams(userTeams: Team[]) {
    teams.value = userTeams
    if (process.client) {
      localStorage.setItem('teams', JSON.stringify(userTeams))
    }
  }

  /**
   * Clear authentication data (logout)
   */
  function clearAuth() {
    token.value = null
    refreshToken.value = null
    tokenExpiresAt.value = null
    user.value = null
    teams.value = []
    error.value = null

    // Clear localStorage
    if (process.client) {
      localStorage.removeItem('auth_token')
      localStorage.removeItem('refresh_token')
      localStorage.removeItem('token_expires_at')
      localStorage.removeItem('user')
      localStorage.removeItem('teams')
    }
  }

  /**
   * Refresh access token using refresh token
   */
  async function refreshAccessToken() {
    if (!refreshToken.value) {
      clearAuth()
      return false
    }

    isLoading.value = true
    error.value = null

    try {
      const config = useRuntimeConfig()
      const response = await $fetch<{
        access_token: string
        expires_in: number
      }>(`${config.public.apiUrl}/api/auth/refresh`, {
        method: 'POST',
        body: {
          refresh_token: refreshToken.value,
        },
      })

      token.value = response.access_token
      tokenExpiresAt.value = Date.now() + response.expires_in * 1000

      // Update localStorage
      if (process.client) {
        localStorage.setItem('auth_token', response.access_token)
        localStorage.setItem('token_expires_at', tokenExpiresAt.value.toString())
      }

      return true
    } catch (err: any) {
      console.error('Failed to refresh token:', err)
      error.value = err.message || 'Failed to refresh authentication'
      clearAuth()
      return false
    } finally {
      isLoading.value = false
    }
  }

  /**
   * Redirect to Discord OAuth login
   */
  function loginWithDiscord() {
    const config = useRuntimeConfig()
    const clientId = config.public.discordClientId
    const redirectUri = config.public.discordRedirectUri

    if (!clientId || !redirectUri) {
      error.value = 'Discord OAuth not configured'
      console.error('Missing Discord OAuth configuration')
      return
    }

    // Generate random state for CSRF protection
    const state = Math.random().toString(36).substring(7)
    if (process.client) {
      sessionStorage.setItem('oauth_state', state)
    }

    // Build Discord OAuth URL
    const params = new URLSearchParams({
      client_id: clientId,
      redirect_uri: redirectUri,
      response_type: 'code',
      scope: 'identify email',
      state,
    })

    const authUrl = `https://discord.com/api/oauth2/authorize?${params.toString()}`

    // Redirect to Discord
    if (process.client) {
      window.location.href = authUrl
    }
  }

  /**
   * Handle Discord OAuth callback
   */
  async function handleDiscordCallback(code: string, state: string) {
    if (process.client) {
      const storedState = sessionStorage.getItem('oauth_state')
      if (!storedState || storedState !== state) {
        error.value = 'Invalid OAuth state - possible CSRF attack'
        return false
      }
      sessionStorage.removeItem('oauth_state')
    }

    isLoading.value = true
    error.value = null

    try {
      const config = useRuntimeConfig()
      const response = await $fetch<{
        access_token: string
        refresh_token: string
        expires_in: number
        user: DiscordUser
      }>(`${config.public.apiUrl}/api/auth/discord/callback`, {
        method: 'POST',
        body: { code, state },
      })

      setAuth(response)

      // Load user teams
      await loadUserTeams()

      return true
    } catch (err: any) {
      console.error('Discord OAuth callback failed:', err)
      error.value = err.message || 'Authentication failed'
      return false
    } finally {
      isLoading.value = false
    }
  }

  /**
   * Load user's teams from API
   */
  async function loadUserTeams() {
    if (!token.value) return

    try {
      const config = useRuntimeConfig()
      const response = await $fetch<{ teams: Team[] }>(
        `${config.public.apiUrl}/api/auth/me`,
        {
          headers: {
            Authorization: `Bearer ${token.value}`,
          },
        }
      )

      setTeams(response.teams)
    } catch (err: any) {
      console.error('Failed to load user teams:', err)
      // Don't set error - teams are optional
    }
  }

  /**
   * Logout user
   */
  function logout() {
    clearAuth()
    // Redirect to home page
    if (process.client) {
      navigateTo('/')
    }
  }

  // ============================================================================
  // Return Store API
  // ============================================================================

  return {
    // State
    token: readonly(token),
    refreshToken: readonly(refreshToken),
    user: readonly(user),
    teams: readonly(teams),
    isLoading: readonly(isLoading),
    error: readonly(error),

    // Getters
    isAuthenticated,
    isTokenValid,
    needsRefresh,
    currentUser,
    userTeams,
    userId,

    // Actions
    initializeAuth,
    setAuth,
    setTeams,
    clearAuth,
    refreshAccessToken,
    loginWithDiscord,
    handleDiscordCallback,
    loadUserTeams,
    logout,
  }
})
