<script setup lang="ts">
definePageMeta({ middleware: ['auth'] })

const route = useRoute()
const router = useRouter()
const billing = useBilling()
const auth = useAuth()
const config = useRuntimeConfig()
const switching = ref<'pro' | 'business' | null>(null)
const portalLoading = ref(false)
const error = ref<string | null>(null)
const toast = ref<string | null>(null)
let toastTimer: ReturnType<typeof setTimeout> | null = null

// Your data
const exporting = ref(false)
const deleteConfirmOpen = ref(false)
const deleteConfirmation = ref('')
const deleting = ref(false)
const deleteError = ref<string | null>(null)

async function exportData() {
  exporting.value = true
  try {
    const apiBase = config.public.apiBase as string
    const token = auth.liveAccessToken()
    // Plain fetch (not useApi) so the response is treated as a download.
    const res = await fetch(`${apiBase}/me/data-export`, {
      headers: token ? { Authorization: `Bearer ${token}` } : {},
      credentials: 'include',
    })
    if (!res.ok) throw new Error(`HTTP ${res.status}`)
    const blob = await res.blob()
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = 'guestguard-data-export.json'
    a.click()
    URL.revokeObjectURL(url)
    showToast('Export downloaded.')
  } catch (e: any) {
    showToast(useErrMessage(e, 'Export failed'))
  } finally {
    exporting.value = false
  }
}

async function confirmDelete() {
  deleting.value = true
  deleteError.value = null
  try {
    await useApi('/me', { method: 'DELETE' })
    // Soft-delete revoked our refresh token; clear local session and
    // bounce to the marketing landing.
    auth.clearSession()
    await router.push('/')
  } catch (e: any) {
    deleteError.value = useErrMessage(e, 'Could not delete account')
  } finally {
    deleting.value = false
  }
}

function showToast(text: string) {
  toast.value = text
  if (toastTimer) clearTimeout(toastTimer)
  toastTimer = setTimeout(() => { toast.value = null }, 5000)
}

onMounted(async () => {
  await billing.fetchStatus()

  // Handle return-from-Stripe query params. ?billing=success means the
  // checkout completed; Stripe also fires the webhook server-side so we
  // refetch status to pick up the new tier without a hard reload.
  const flag = route.query.billing
  if (flag === 'success') {
    showToast('Subscription updated — welcome aboard!')
    // Stripe's webhook may take ~1s to land. Poll a couple of times.
    for (let i = 0; i < 3; i++) {
      await new Promise((r) => setTimeout(r, 1500))
      await billing.fetchStatus()
      if (billing.status.value?.tier !== 'free') break
    }
  } else if (flag === 'cancelled') {
    showToast('No worries — your plan is unchanged.')
  }
})

async function upgrade(tier: 'pro' | 'business') {
  switching.value = tier
  error.value = null
  try {
    await billing.startCheckout(tier)
  } catch (e: any) {
    if (e?.response?.status === 503) {
      error.value = 'Billing isn\'t enabled on this environment yet — contact support.'
    } else {
      error.value = useErrMessage(e, 'Could not start checkout')
    }
  } finally {
    switching.value = null
  }
}

async function manageSubscription() {
  portalLoading.value = true
  error.value = null
  try {
    await billing.openPortal()
  } catch (e: any) {
    if (e?.response?.status === 503) {
      error.value = 'Billing isn\'t enabled on this environment yet.'
    } else {
      error.value = useErrMessage(e, 'Could not open the billing portal')
    }
  } finally {
    portalLoading.value = false
  }
}

// Usage bar percentage — clamps to [0, 100] for the progress indicator.
const eventsUsagePct = computed(() => {
  const s = billing.status.value
  if (!s) return 0
  const limit = s.limits.events_per_month
  if (limit < 0) return 0 // unlimited — show empty bar
  if (limit === 0) return 100
  return Math.min(100, Math.round((s.usage.events_this_month / limit) * 100))
})

function formatLimit(n: number): string {
  return n < 0 ? 'Unlimited' : n.toLocaleString()
}

function periodEndLabel(iso?: string): string {
  if (!iso) return ''
  try {
    return new Date(iso).toLocaleDateString(undefined, { day: 'numeric', month: 'short', year: 'numeric' })
  } catch {
    return iso
  }
}
</script>

<template>
  <section class="space-y-6">
    <div>
      <NuxtLink to="/dashboard" class="mb-2 inline-block text-sm text-zinc-400 hover:text-zinc-200">
        ← Back to dashboard
      </NuxtLink>
      <h1 class="text-2xl font-semibold">Billing &amp; plan</h1>
      <p class="mt-1 text-sm text-zinc-400">
        Change your plan, see your usage, or update your payment method.
      </p>
    </div>

    <ClientOnly>
      <!-- Current plan + usage -->
      <div class="card">
        <div class="flex flex-wrap items-start justify-between gap-4">
          <div>
            <p class="text-xs font-medium uppercase tracking-wider text-zinc-500">Current plan</p>
            <div class="mt-1 flex items-baseline gap-2">
              <span class="text-2xl font-semibold capitalize text-zinc-100">{{ billing.status.value?.tier || '—' }}</span>
              <span
                v-if="billing.status.value && billing.status.value.tier !== 'free'"
                class="rounded-full bg-zinc-800 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-zinc-400"
              >{{ billing.status.value.status }}</span>
            </div>
            <p
              v-if="billing.status.value?.current_period_end && billing.status.value.tier !== 'free'"
              class="mt-1 text-xs text-zinc-500"
            >
              <template v-if="billing.status.value.cancel_at_period_end">
                Cancels on {{ periodEndLabel(billing.status.value.current_period_end) }}.
              </template>
              <template v-else>
                Renews on {{ periodEndLabel(billing.status.value.current_period_end) }}.
              </template>
            </p>
          </div>
          <button
            v-if="billing.status.value?.portal_available"
            type="button"
            class="rounded-md border border-zinc-700 px-3 py-1.5 text-sm text-zinc-200 transition hover:border-zinc-500 hover:bg-zinc-800 disabled:opacity-50"
            :disabled="portalLoading"
            @click="manageSubscription"
          >
            {{ portalLoading ? 'Opening…' : 'Manage subscription' }}
          </button>
        </div>

        <!-- Usage bar -->
        <div class="mt-5">
          <div class="mb-1.5 flex items-center justify-between text-xs">
            <span class="text-zinc-300">Events this month</span>
            <span class="tabular-nums text-zinc-400">
              {{ billing.status.value?.usage.events_this_month ?? 0 }}
              of
              {{ formatLimit(billing.status.value?.limits.events_per_month ?? 0) }}
            </span>
          </div>
          <div class="h-2 w-full overflow-hidden rounded-full bg-zinc-800">
            <div
              class="h-full rounded-full transition-all"
              :class="eventsUsagePct >= 90 ? 'bg-amber-400' : 'bg-brand-500'"
              :style="{ width: `${eventsUsagePct}%` }"
            ></div>
          </div>
          <p class="mt-1.5 text-xs text-zinc-500">
            Guest cap per event: {{ formatLimit(billing.status.value?.limits.guests_per_event ?? 0) }}.
          </p>
        </div>
      </div>

      <!-- Pricing cards -->
      <div class="grid gap-4 md:grid-cols-3">
        <div
          v-for="t in TIER_CARDS"
          :key="t.id"
          class="card relative flex flex-col gap-4"
          :class="t.highlight ? 'border-brand-700/60 bg-brand-500/[0.04]' : ''"
        >
          <span
            v-if="t.id === billing.status.value?.tier"
            class="absolute right-3 top-3 rounded-full bg-zinc-800 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-zinc-300"
          >Current</span>
          <span
            v-else-if="t.highlight"
            class="absolute right-3 top-3 rounded-full bg-brand-500 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-zinc-950"
          >Most popular</span>

          <div>
            <h3 class="text-lg font-semibold capitalize text-zinc-100">{{ t.name }}</h3>
            <p class="mt-1 text-xs text-zinc-500">{{ t.tagline }}</p>
          </div>

          <div>
            <span class="text-3xl font-semibold tabular-nums text-zinc-100">{{ t.price }}</span>
            <span class="ml-1 text-xs text-zinc-500">{{ t.priceSubtitle }}</span>
          </div>

          <ul class="space-y-1.5 text-sm text-zinc-300">
            <li v-for="f in t.features" :key="f" class="flex items-start gap-2">
              <svg class="mt-0.5 h-3.5 w-3.5 shrink-0 text-brand-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
                <path fill-rule="evenodd" d="M16.704 5.296a1 1 0 010 1.408l-8 8a1 1 0 01-1.408 0l-4-4a1 1 0 011.408-1.408L8 12.592l7.296-7.296a1 1 0 011.408 0z" clip-rule="evenodd" />
              </svg>
              <span>{{ f }}</span>
            </li>
          </ul>

          <div class="mt-auto pt-2">
            <button
              v-if="t.id === billing.status.value?.tier"
              type="button"
              class="w-full cursor-default rounded-md border border-zinc-800 px-3 py-2 text-sm text-zinc-500"
              disabled
            >Current plan</button>
            <button
              v-else-if="t.id === 'free'"
              type="button"
              class="w-full cursor-default rounded-md border border-zinc-800 px-3 py-2 text-sm text-zinc-500"
              disabled
            >Downgrade in the billing portal</button>
            <button
              v-else
              type="button"
              class="btn-primary w-full disabled:opacity-50"
              :disabled="switching === t.id"
              @click="upgrade(t.id)"
            >
              {{ switching === t.id ? 'Opening checkout…' : `Upgrade to ${t.name}` }}
            </button>
          </div>
        </div>
      </div>

      <p v-if="error" class="text-sm text-red-400">{{ error }}</p>

      <p class="text-xs text-zinc-500">
        Receipts and invoices are emailed automatically by Stripe.
        Need to cancel? Use <a href="#" class="text-brand-400 hover:text-brand-300" @click.prevent="manageSubscription">Manage subscription</a> above.
      </p>

      <!-- ===== Your data ===== -->
      <div class="card mt-2">
        <h2 class="mb-1 text-lg font-semibold">Your data</h2>
        <p class="mb-4 text-xs text-zinc-500">
          Export a copy of everything we hold about you, or delete your account.
        </p>
        <div class="space-y-3">
          <button
            type="button"
            class="flex w-full items-center justify-between rounded-md border border-zinc-700 bg-zinc-950 px-3 py-3 text-left transition hover:border-zinc-500 hover:bg-zinc-900 disabled:opacity-50"
            :disabled="exporting"
            @click="exportData"
          >
            <span>
              <span class="block text-sm font-medium text-zinc-100">Export my data</span>
              <span class="block text-xs text-zinc-500">
                Download a JSON file with your events, guests, RSVPs, and account info.
              </span>
            </span>
            <span class="text-xs text-zinc-400">{{ exporting ? '…' : '↓' }}</span>
          </button>

          <button
            type="button"
            class="flex w-full items-center justify-between rounded-md border border-red-800/40 bg-red-950/10 px-3 py-3 text-left transition hover:border-red-700 hover:bg-red-950/20"
            @click="deleteConfirmOpen = true"
          >
            <span>
              <span class="block text-sm font-medium text-red-300">Delete my account</span>
              <span class="block text-xs text-red-400/70">
                Soft-deleted immediately, permanently erased after 30 days. You'll be signed out everywhere.
              </span>
            </span>
            <span class="text-xs text-red-400">→</span>
          </button>
        </div>
      </div>

      <template #fallback>
        <div class="card text-sm text-zinc-500">Loading…</div>
      </template>
    </ClientOnly>

    <!-- Delete-account confirmation -->
    <Teleport to="body">
      <div
        v-if="deleteConfirmOpen"
        class="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4 backdrop-blur-sm"
        @click.self="deleteConfirmOpen = false"
      >
        <div
          role="alertdialog"
          aria-modal="true"
          aria-labelledby="del-acct-title"
          class="w-full max-w-md rounded-lg border border-zinc-800 bg-zinc-900 p-5 shadow-2xl"
        >
          <h3 id="del-acct-title" class="mb-1 text-base font-semibold">Delete account?</h3>
          <p class="mb-3 text-sm text-zinc-400">
            Your account will be soft-deleted now and permanently erased
            after 30 days. All your events, guests, and RSVP history go
            with it. You'll be signed out from every device.
          </p>
          <p class="mb-3 text-xs text-zinc-500">
            Type <code class="rounded bg-zinc-800 px-1 py-0.5 font-mono text-zinc-300">delete</code>
            to confirm.
          </p>
          <input
            v-model="deleteConfirmation"
            type="text"
            placeholder="delete"
            class="input mb-3 font-mono"
            autocomplete="off"
          />
          <div class="flex items-center justify-end gap-2">
            <button class="text-sm text-zinc-400 hover:text-zinc-200" :disabled="deleting" @click="deleteConfirmOpen = false">Cancel</button>
            <button
              class="rounded-md bg-red-500/90 px-3 py-1.5 text-sm font-medium text-white shadow-sm transition hover:bg-red-500 disabled:opacity-40"
              :disabled="deleting || deleteConfirmation.trim().toLowerCase() !== 'delete'"
              @click="confirmDelete"
            >
              {{ deleting ? 'Deleting…' : 'Delete forever' }}
            </button>
          </div>
          <p v-if="deleteError" class="mt-3 text-sm text-red-400">{{ deleteError }}</p>
        </div>
      </div>
    </Teleport>

    <!-- Toast for return-from-Stripe -->
    <Transition
      enter-active-class="transition duration-200 ease-out"
      enter-from-class="translate-y-2 opacity-0"
      enter-to-class="translate-y-0 opacity-100"
      leave-active-class="transition duration-200 ease-in"
      leave-from-class="translate-y-0 opacity-100"
      leave-to-class="translate-y-2 opacity-0"
    >
      <button
        v-if="toast"
        type="button"
        class="fixed bottom-6 right-6 z-50 max-w-sm rounded-lg border border-brand-700/60 bg-brand-950/90 px-4 py-3 text-left text-sm text-brand-100 shadow-lg backdrop-blur"
        @click="toast = null"
      >
        <span aria-hidden="true" class="mr-2">✓</span>{{ toast }}
      </button>
    </Transition>
  </section>
</template>
