/**
 * Pinia auth — access token in memory; refresh in HttpOnly cookie.
 */
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { ApiError, TotpRequiredError, api, http } from '@/api'

export { TotpRequiredError }

export const useAuthStore = defineStore('auth', () => {
  const token = ref<string | null>(null)
  const admin = ref<AdminProfile | null>(null)
  const bootstrapped = ref(false)

  const isLoggedIn = computed(() => !!token.value)

  function setAccessToken(accessToken: string) {
    token.value = accessToken
  }

  async function tryRestoreSession() {
    if (token.value) {
      bootstrapped.value = true
      return true
    }
    try {
      const res = await api<{ access_token?: string }>('/auth/refresh', {
        method: 'POST',
        body: JSON.stringify({}),
        _retry: true,
      })
      if (res?.access_token) {
        token.value = res.access_token
        await fetchProfile()
        bootstrapped.value = true
        return true
      }
    } catch {
      /* no valid refresh cookie */
    }
    bootstrapped.value = true
    return false
  }

  async function login(username: string, password: string, totp_code?: string) {
    const res = await api<{ access_token?: string; admin?: AdminProfile }>('/auth/login', {
      method: 'POST',
      body: JSON.stringify({ username, password, totp_code }),
      _retry: true,
    })

    if (res.access_token) {
      token.value = res.access_token
      if (res.admin) {
        admin.value = res.admin
      } else {
        await fetchProfile()
      }
      bootstrapped.value = true
      return
    }
    await fetchProfile()
  }

  async function fetchProfile() {
    if (!token.value) return
    try {
      admin.value = await http.get<AdminProfile>('/auth/me')
    } catch (e: unknown) {
      if (e instanceof ApiError && e.status === 401) {
        forceLogout()
      }
    }
  }

  function logout() {
    token.value = null
    admin.value = null
    http.post('/auth/logout').catch(() => {})
  }

  function forceLogout() {
    token.value = null
    admin.value = null
  }

  return {
    token,
    admin,
    isLoggedIn,
    bootstrapped,
    setAccessToken,
    tryRestoreSession,
    login,
    fetchProfile,
    logout,
    forceLogout,
  }
})

interface AdminProfile {
  id: number
  username: string
  totp_enabled: boolean
  created_at: string
}
