import { defineStore } from 'pinia'
import { api, setAuthToken, setRefreshToken, onSessionExpiredCallback } from '@/api/client'
import router from '@/router'

let refreshTimer = null

function scheduleRefresh(expiresAt, store) {
  clearTimeout(refreshTimer)
  const expiresMs = new Date(expiresAt).getTime()
  const now = Date.now()
  const delay = Math.max((expiresMs - now) - 60_000, 5_000)
  refreshTimer = setTimeout(() => store.silentRefresh(), delay)
}

export const useAuthStore = defineStore('auth', {
  state: () => ({
    token: localStorage.getItem('vigilcare_token') ?? null,
    _refreshToken: localStorage.getItem('vigilcare_refresh_token') ?? null,
    user: JSON.parse(localStorage.getItem('vigilcare_user') ?? 'null'),
    expiresAt: localStorage.getItem('vigilcare_expires_at') ?? null,
  }),

  getters: {
    isAuthenticated: (state) => !!state.token,
    role: (state) => state.user?.role ?? null,
    isAdmin: (state) => state.user?.role === 'ADMIN',
    isNurse: (state) => state.user?.role === 'NURSE',
    isPhysician: (state) => state.user?.role === 'PHYSICIAN',
    displayName: (state) =>
      state.user?.displayName ?? state.user?.username ?? 'Unknown user',
    userId: (state) => state.user?.userId ?? null,
  },

  actions: {
    async login(username, password) {
      const data = await api.post('/api/v1/auth/login', { username, password })
      this.token = data.accessToken
      this._refreshToken = data.refreshToken
      this.expiresAt = data.expiresAt
      this.user = {
        userId: data.userId,
        username: data.username,
        displayName: data.displayName,
        role: data.role,
      }
      localStorage.setItem('vigilcare_token', this.token)
      localStorage.setItem('vigilcare_refresh_token', this._refreshToken)
      localStorage.setItem('vigilcare_expires_at', this.expiresAt)
      localStorage.setItem('vigilcare_user', JSON.stringify(this.user))
      setAuthToken(this.token)
      setRefreshToken(this._refreshToken)
      scheduleRefresh(this.expiresAt, this)
    },

    async logout() {
      try {
        if (this._refreshToken) {
          await api.post('/api/v1/auth/logout', { refreshToken: this._refreshToken })
        }
      } catch {
        // Best-effort server-side revocation
      }
      this._clearSession()
      router.push('/login')
    },

    _clearSession() {
      clearTimeout(refreshTimer)
      this.token = null
      this._refreshToken = null
      this.expiresAt = null
      this.user = null
      localStorage.removeItem('vigilcare_token')
      localStorage.removeItem('vigilcare_refresh_token')
      localStorage.removeItem('vigilcare_expires_at')
      localStorage.removeItem('vigilcare_user')
      setAuthToken(null)
      setRefreshToken(null)
    },

    async silentRefresh() {
      if (!this._refreshToken) return
      try {
        const data = await api.post('/api/v1/auth/refresh', {
          refreshToken: this._refreshToken,
        })
        this._applyTokens(data.accessToken, data.refreshToken, data.expiresAt)
      } catch {
        this._clearSession()
        router.push('/login')
      }
    },

    _applyTokens(accessToken, newRefreshToken, expiresAt) {
      this.token = accessToken
      this._refreshToken = newRefreshToken
      this.expiresAt = expiresAt
      localStorage.setItem('vigilcare_token', accessToken)
      localStorage.setItem('vigilcare_refresh_token', newRefreshToken)
      localStorage.setItem('vigilcare_expires_at', expiresAt)
      setAuthToken(accessToken)
      setRefreshToken(newRefreshToken)
      scheduleRefresh(expiresAt, this)
    },

    hydrate() {
      if (this.token) {
        setAuthToken(this.token)
        setRefreshToken(this._refreshToken)

        onSessionExpiredCallback((event) => {
          if (event.type === 'refreshed') {
            this._applyTokens(event.accessToken, event.refreshToken, event.expiresAt)
          } else {
            this._clearSession()
            router.push('/login')
          }
        })

        if (this.expiresAt) {
          scheduleRefresh(this.expiresAt, this)
        }
      }
    },
  },
})
