import { defineStore } from 'pinia' import { pb } from '../services/pocketbase' import * as tenantRepository from '../repositories/tenant_repository' // Global auth/tenant state โ€” session persistence itself is handled by // pb.authStore (localStorage-backed), this store layers Bettersight's // tenant/tier/onboarding state on top and exposes the actions pages // call, per CLAUDE.md ยง5b ("Stores โ†’ global state only, calls // repositories for data, NO API calls directly"). export const useAuthStore = defineStore('auth', { state: () => ({ email: null, tenant: null, loading: false, error: null }), getters: { isAuthenticated: () => pb.authStore.isValid, tenantId: (state) => state.tenant?.id ?? null, tier: (state) => state.tenant?.tier ?? null, onboarding: (state) => state.tenant?.onboarding_checklist ?? {} }, actions: { async loginWithPassword(email, password) { this.loading = true this.error = null try { await pb.collection('users').authWithPassword(email, password) await this.fetchTenant() } catch (err) { this.error = err?.response?.message || 'Invalid email or password' throw err } finally { this.loading = false } }, async loginWithGoogle() { this.loading = true this.error = null try { await pb.collection('users').authWithOAuth2({ provider: 'google' }) await this.fetchTenant() } catch (err) { this.error = err?.message || 'Google sign-in failed' throw err } finally { this.loading = false } }, async requestPasswordReset(email) { await pb.collection('users').requestPasswordReset(email) }, async confirmPasswordReset(token, password, passwordConfirm) { await pb.collection('users').confirmPasswordReset(token, password, passwordConfirm) }, async fetchTenant() { this.email = pb.authStore.model?.email ?? null this.tenant = await tenantRepository.getMe() // No signup form exists in this dashboard's scope (account // creation is via Stripe webhook or the manual onboarding // runbook), so first login is the earliest point browser JS can // capture the PM's timezone. Once persisted, getMe() returns it // going forward and this never fires again for that tenant. if (this.tenant && !this.tenant.timezone) { try { const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone this.tenant.timezone = await tenantRepository.captureTimezone(timezone) } catch { // Side effect โ€” never blocks login if this fails. } } }, async restoreSession() { if (!pb.authStore.isValid) return try { await pb.collection('users').authRefresh() await this.fetchTenant() } catch { this.clearSession() } }, async updateOnboarding(updates) { const checklist = await tenantRepository.updateOnboarding(updates) if (this.tenant) this.tenant.onboarding_checklist = checklist return checklist }, clearSession() { pb.authStore.clear() this.email = null this.tenant = null } } })