import { defineStore } from 'pinia'
import { ref } from 'vue'
import { getPortalUser } from 'src/api/portal'

// sessionStorage key holding the raw magic-link JWT for the current tab session.
// Read by src/api/payments.js to authorize /payments/* calls — keep the two in sync.
const TOKEN_KEY = 'targo_portal_jwt'

/**
 * Customer session store.
 *
 * Two hydration paths:
 *   1. Magic-link JWT in the URL (`?token=JWT`). Decoded client-side — the
 *      hub already signed it and the user received it through their own
 *      verified channel (SMS/email), so trust is established. No network
 *      call needed.
 *   2. ERPNext session (legacy / staff impersonation). Only tried when
 *      there's no token AND no existing store state. Failure is silent —
 *      the router guard will bounce the user to /login.
 *
 * For the token path we also strip `?token=` from the URL so a page refresh
 * or bookmark doesn't replay the token forever. The store state carries us
 * for the rest of the session; if the user refreshes without a token, the
 * guard sees `customerId` still set and lets them through.
 */

function readTokenFromLocation () {
  if (typeof window === 'undefined') return ''
  const hash = window.location.hash || ''
  // Hash form: #/paiement/merci?token=xxx OR #/?token=xxx
  const qIdx = hash.indexOf('?')
  if (qIdx === -1) return ''
  const qs = new URLSearchParams(hash.slice(qIdx + 1))
  return qs.get('token') || ''
}

function decodeJwtPayload (token) {
  try {
    const parts = token.split('.')
    if (parts.length !== 3) return null
    const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')))
    if (payload.exp && Date.now() / 1000 > payload.exp) return null
    return payload
  } catch {
    return null
  }
}

function stripTokenFromUrl () {
  if (typeof window === 'undefined') return
  const hash = window.location.hash || ''
  const qIdx = hash.indexOf('?')
  if (qIdx === -1) return
  const before = hash.slice(0, qIdx)
  const params = new URLSearchParams(hash.slice(qIdx + 1))
  params.delete('token')
  const rest = params.toString()
  const newHash = rest ? `${before}?${rest}` : before
  // Use replaceState so the token doesn't stay in browser history
  window.history.replaceState(null, '', window.location.pathname + window.location.search + newHash)
}

export const useCustomerStore = defineStore('customer', () => {
  const email = ref('')
  const customerId = ref('')
  const customerName = ref('')
  const token = ref('')
  const loading = ref(true)
  const error = ref(null)

  function hydrateFromToken () {
    const t = readTokenFromLocation()
    if (!t) return false
    const payload = decodeJwtPayload(t)
    if (!payload || payload.scope !== 'customer') return false
    customerId.value = payload.sub
    customerName.value = payload.name || payload.sub
    email.value = payload.email || ''
    token.value = t
    try { sessionStorage.setItem(TOKEN_KEY, t) } catch { /* private mode */ }
    stripTokenFromUrl()
    return true
  }

  async function init () {
    loading.value = true
    error.value = null
    try {
      // Path 1: magic-link token in URL
      if (hydrateFromToken()) return

      // Restore a prior magic-link session (sessionStorage) so a page reload keeps
      // both the identity AND the raw token we send on /payments/* calls.
      if (!customerId.value) {
        let saved = ''
        try { saved = sessionStorage.getItem(TOKEN_KEY) || '' } catch { saved = '' }
        if (saved) {
          const payload = decodeJwtPayload(saved)
          if (payload && payload.scope === 'customer') {
            token.value = saved
            customerId.value = payload.sub
            customerName.value = payload.name || payload.sub
            email.value = payload.email || ''
            return
          }
          try { sessionStorage.removeItem(TOKEN_KEY) } catch { /* expired/invalid */ }
        }
      }

      // Already authenticated in this tab? (e.g. subsequent nav)
      if (customerId.value) return

      // Path 2: fall back to ERPNext session (staff impersonation / legacy)
      const user = await getPortalUser()
      email.value = user.email
      customerId.value = user.customer_id
      customerName.value = user.customer_name
    } catch (e) {
      // Silent — router guard will push to /login when customerId is empty
      error.value = null
    } finally {
      loading.value = false
    }
  }

  function clear () {
    email.value = ''
    customerId.value = ''
    customerName.value = ''
    token.value = ''
    error.value = null
    try { sessionStorage.removeItem(TOKEN_KEY) } catch { /* ignore */ }
  }

  return { email, customerId, customerName, token, loading, error, init, hydrateFromToken, clear }
})
