import { defineStore } from 'pinia'
import { computed, ref } from 'vue'

import { type User } from '@/api/generated/crabs/evening_detective_server'
import { buildClient } from '@/api/generated/crabs/evening_detective_server/client'

export const useAuthStore = defineStore('auth', () => {
  // ===== STATE =====
  const accessToken = ref<string | null>(null)
  const refreshToken = ref<string | null>(null)
  const user = ref<User | null>(null)
  const isLoading = ref(false)
  const error = ref<string | null>(null)

  // ===== GETTERS =====
  const isAuthenticated = computed(() => !!accessToken.value)
  const username = computed(() => user.value?.username || '')
  const userRoles = computed(() => user.value?.roles || [])

  // ===== ACTIONS =====

  // Инициализация из localStorage при загрузке
  function initFromStorage() {
    const token = localStorage.getItem('accessToken')
    const refresh = localStorage.getItem('refreshToken')

    if (token) {
      accessToken.value = token
      refreshToken.value = refresh

      // Получаем данные пользователя
      fetchUser()
    }
  }

  function getToken(): string | null {
    return accessToken.value
  }

  // Получение данных пользователя
  async function fetchUser() {
    if (!accessToken.value) return

    try {
      const client = buildClient(getToken)
      const response = await client.GetMe({})

      if (response.error) {
        error.value = response.error
        return
      }

      if (response.user) {
        user.value = response.user
      }
    } catch (err) {
      console.error('Failed to fetch user:', err)
      // Если 401 — токен протух
      if (err instanceof Error && err.message.includes('401')) {
        await logout()
      }
    }
  }

  // Логин
  async function login(email: string, password: string) {
    isLoading.value = true
    error.value = null

    try {
      const client = buildClient(getToken)
      const response = await client.Login({ email, password })

      if (response.error) {
        error.value = response.error
        return false
      }

      // Сохраняем токены
      if (response.accessToken) {
        accessToken.value = response.accessToken
        refreshToken.value = response.refreshToken || null

        // Сохраняем в localStorage
        localStorage.setItem('accessToken', response.accessToken)
        if (response.refreshToken) {
          localStorage.setItem('refreshToken', response.refreshToken)
        }

        // Получаем данные пользователя
        await fetchUser()

        return true
      }

      return false
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Login failed'
      return false
    } finally {
      isLoading.value = false
    }
  }

  // Обновление токена
  async function refreshTokenAction() {
    if (!refreshToken.value) return false

    try {
      const client = buildClient(getToken)
      const response = await client.Refresh({
        refreshToken: refreshToken.value,
      })

      if (response.error || !response.accessToken) {
        return false
      }

      // Обновляем токены
      accessToken.value = response.accessToken
      refreshToken.value = response.refreshToken || null

      localStorage.setItem('accessToken', response.accessToken)
      if (response.refreshToken) {
        localStorage.setItem('refreshToken', response.refreshToken)
      }

      return true
    } catch {
      return false
    }
  }

  // Регистрация
  async function signup(username: string, email: string) {
    isLoading.value = true
    error.value = null

    try {
      const client = buildClient(getToken)
      const response = await client.Signup({ username, email })

      if (response.error) {
        error.value = response.error
        return false
      }

      return true
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Signup failed'
      return false
    } finally {
      isLoading.value = false
    }
  }

  // Восстановление пароля
  async function refreshPassword(email: string) {
    isLoading.value = true
    error.value = null

    try {
      const client = buildClient(getToken)
      const response = await client.RefreshPassword({ email })

      if (response.error) {
        error.value = response.error
        return false
      }

      return true
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Password reset failed'
      return false
    } finally {
      isLoading.value = false
    }
  }

  // Выход
  async function logout() {
    accessToken.value = null
    refreshToken.value = null
    user.value = null
    error.value = null

    localStorage.removeItem('accessToken')
    localStorage.removeItem('refreshToken')
  }

  // Проверка ролей
  function hasRole(role: string): boolean {
    return userRoles.value.includes(role)
  }

  function hasAnyRole(roles: string[]): boolean {
    return roles.some((role) => userRoles.value.includes(role))
  }

  // ===== RETURN =====
  return {
    // State
    accessToken,
    refreshToken,
    user,
    isLoading,
    error,

    // Getters
    isAuthenticated,
    username,
    userRoles,

    // Actions
    initFromStorage,
    getToken,
    login,
    signup,
    refreshPassword,
    logout,
    fetchUser,
    refreshTokenAction,
    hasRole,
    hasAnyRole,
  }
})
