import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { User, License } from '@/types'

/**
 * Decode the permissions object from a JWT access token payload.
 * JWTs are base64url-encoded — the payload is not secret, just signed.
 * The backend JWT strategy embeds `permissions: role?.permissions || {}`
 * which is a JSONB object from the Role entity (e.g. { 'server.view': true }).
 * Returns an empty object if the token is missing or malformed.
 */
function decodeJwtPermissions(token: string): Record<string, boolean> {
  try {
    const payloadB64 = token.split('.')[1]
    if (!payloadB64) return {}
    const json = atob(payloadB64.replace(/-/g, '+').replace(/_/g, '/'))
    const payload = JSON.parse(json)
    return payload.permissions && typeof payload.permissions === 'object'
      ? payload.permissions
      : {}
  } catch {
    return {}
  }
}

export const useAuthStore = defineStore('auth', () => {
  const user = ref<User | null>(null)
  const license = ref<License | null>(null)
  const accessToken = ref<string | null>(null)
  const refreshToken = ref<string | null>(null)
  // Permissions decoded from the JWT payload — reflects the user's actual role permissions.
  // Stored separately so hasPermission() works after page reload (token is persisted).
  const permissions = ref<Record<string, boolean>>({})

  const isAuthenticated = computed(() => !!accessToken.value)
  const isSuperAdmin = computed(() => user.value?.is_super_admin ?? false)
  const hasLicense = computed(() => !!license.value)
  const isLicenseActive = computed(() => license.value?.status === 'active')

  function setAuth(data: { access_token: string; refresh_token: string; user: User }) {
    accessToken.value = data.access_token
    refreshToken.value = data.refresh_token
    user.value = data.user
    // Decode permissions from the JWT so hasPermission() reflects the real role,
    // not a hardcoded list. Custom roles work automatically this way.
    permissions.value = decodeJwtPermissions(data.access_token)
  }

  function setLicense(data: License) {
    license.value = data
  }

  function logout() {
    user.value = null
    license.value = null
    accessToken.value = null
    refreshToken.value = null
    permissions.value = {}
  }

  /**
   * Validate the persisted session against the API on app boot. Without this,
   * a stale/revoked token renders the full panel chrome and only collapses on
   * the first real API call. useApi's 401 path (refresh → retry → logout)
   * does the heavy lifting; any non-auth failure (network, 5xx) keeps the
   * session — never log users out because the API blipped.
   * Dynamic import avoids a static auth-store ↔ useApi module cycle.
   */
  async function validateSession(): Promise<void> {
    if (!accessToken.value) return
    try {
      const { useApi } = await import('@/composables/useApi')
      const me = await useApi().get<Partial<User>>('/auth/me')
      if (user.value && me && typeof me === 'object') {
        user.value = { ...user.value, ...me }
      }
    } catch {
      // 401 → refresh → logout/redirect already handled inside useApi.
    }
  }

  function hasModule(moduleSlug: string): boolean {
    return license.value?.modules_enabled?.includes(moduleSlug) ?? false
  }

  function hasPermission(permission: string): boolean {
    // Super admin has all permissions
    if (isSuperAdmin.value) return true

    // Check the permissions decoded from the JWT payload.
    // The backend embeds role permissions as a JSONB object { 'resource.action': true }.
    // If permissions is empty (e.g. after a page reload before re-auth), fall back to
    // re-decoding from the persisted token so the user isn't locked out.
    const perms = Object.keys(permissions.value).length > 0
      ? permissions.value
      : accessToken.value
        ? decodeJwtPermissions(accessToken.value)
        : {}

    return perms[permission] === true
  }

  return {
    user,
    license,
    accessToken,
    refreshToken,
    permissions,
    isAuthenticated,
    isSuperAdmin,
    hasLicense,
    isLicenseActive,
    setAuth,
    setLicense,
    logout,
    validateSession,
    hasModule,
    hasPermission,
  }
}, {
  persist: {
    pick: ['accessToken', 'refreshToken', 'user', 'license'],
  },
})
