<script setup lang="ts">
import type { Tenant, TenantUser } from '~/types/tenant'
import type { AuditEvent } from '~/types/audit'

const route = useRoute()
const slug = computed(() => route.params.slug as string)

const { data: tenant, refresh: refreshTenant } = await useFetch<Tenant>(() => `/api/tenants/${slug.value}`, {
  watch: [slug],
})

const activeTab = ref<'overview' | 'users' | 'resources' | 'billing' | 'audit' | 'support' | 'danger'>('overview')

const impersonate = useImpersonation()

// Lazy-fetch users only when the tab is opened.
const { data: users, refresh: refreshUsers } = useLazyFetch<TenantUser[]>(
  () => `/api/tenants/${slug.value}/users`,
  { immediate: false, default: () => [] },
)
// Lazy-fetch this tenant's audit trail only when the Audit tab is opened.
const { data: auditEvents, refresh: refreshAudit } = useLazyFetch<AuditEvent[]>(
  () => `/api/audit?tenantSlug=${slug.value}&limit=50`,
  { immediate: false, default: () => [] },
)
function fmtAudit(iso: string) {
  return new Date(iso).toLocaleString('da-DK', {
    day: '2-digit',
    month: 'short',
    hour: '2-digit',
    minute: '2-digit',
  })
}

interface TenantInvoice {
  _id: string
  number?: string
  currency: 'DKK' | 'EUR' | 'USD'
  amountDue: number
  status: string
  periodEnd?: string
  createdAt?: string
}
const { data: billingInvoices, refresh: refreshBilling } = useLazyFetch<TenantInvoice[]>(
  () => `/api/billing/tenants/${slug.value}/invoices`,
  { immediate: false, default: () => [] },
)
function invoiceTone(s: string): 'ok' | 'warn' | 'bad' | 'neutral' {
  if (s === 'paid') return 'ok'
  if (s === 'past_due' || s === 'uncollectible') return 'bad'
  if (s === 'open') return 'warn'
  return 'neutral'
}

watch(activeTab, (t) => {
  if (t === 'users' && (users.value?.length ?? 0) === 0) refreshUsers()
  if (t === 'audit' && (auditEvents.value?.length ?? 0) === 0) refreshAudit()
  if (t === 'billing' && (billingInvoices.value?.length ?? 0) === 0) refreshBilling()
})

const tabs = computed(() => [
  { value: 'overview', label: 'Overview' },
  { value: 'users', label: 'Users', count: users.value?.length },
  { value: 'resources', label: 'Resources' },
  { value: 'billing', label: 'Billing' },
  { value: 'audit', label: 'Audit' },
  { value: 'support', label: 'Support' },
  { value: 'danger', label: 'Danger zone' },
])

const STATUS_TONE = {
  active: 'ok', pending: 'warn', suspended: 'bad', deleted: 'neutral',
} as const

const INTEGRATION_TONE = {
  ok: 'ok', skipped: 'neutral', error: 'bad', pending: 'warn',
} as const

// Mongoose subdocs include an `_id` key when serialized — iterate explicitly
// over the integration names we care about so it doesn't leak into the UI.
const INTEGRATIONS = ['authentik', 'stalwart', 'ocis'] as const
type IntegrationKey = (typeof INTEGRATIONS)[number]

// ── Danger-zone state ─────────────────────────────────────────────────────
const dangerAction = ref<'suspend' | 'resume' | 'delete' | null>(null)
const dangerBusy = ref(false)
const dangerError = ref<string | null>(null)
const reconcileBusy = ref(false)
const reconcileMessage = ref<string | null>(null)

async function confirmDanger() {
  if (!dangerAction.value) return
  dangerBusy.value = true
  dangerError.value = null
  try {
    if (dangerAction.value === 'suspend') {
      await $fetch(`/api/tenants/${slug.value}/suspend`, { method: 'POST' })
    } else if (dangerAction.value === 'resume') {
      await $fetch(`/api/tenants/${slug.value}/resume`, { method: 'POST' })
    } else if (dangerAction.value === 'delete') {
      await $fetch(`/api/tenants/${slug.value}`, { method: 'DELETE' })
    }
    await refreshTenant()
    dangerAction.value = null
  } catch (err: unknown) {
    const e = err as { data?: { data?: { message?: string }; message?: string }; statusCode?: number }
    dangerError.value = e.data?.data?.message ?? e.data?.message ?? String(err)
  } finally {
    dangerBusy.value = false
  }
}

async function reconcile() {
  reconcileBusy.value = true
  reconcileMessage.value = null
  try {
    await $fetch(`/api/tenants/${slug.value}/reconcile`, { method: 'POST' })
    await refreshTenant()
    reconcileMessage.value = 'Reconciled. Provisioning state updated.'
  } catch (err: unknown) {
    const e = err as { data?: { data?: { message?: string }; message?: string } }
    reconcileMessage.value = `Failed: ${e.data?.data?.message ?? e.data?.message ?? err}`
  } finally {
    reconcileBusy.value = false
  }
}
</script>

<template>
  <div v-if="tenant">
    <PageHeader
      :eyebrow="`Tenant · ${tenant.slug}`"
      :title="tenant.name"
      :subtitle="`Created ${new Date(tenant.createdAt).toISOString().slice(0, 10)} · ${tenant.domains.length || 0} domain(s)`"
    >
      <template #actions>
        <Badge :tone="STATUS_TONE[tenant.status]" dot>{{ tenant.status }}</Badge>
        <Badge tone="neutral">{{ tenant.plan }}</Badge>
        <UiButton variant="secondary" @click="impersonate.open(tenant)">
          <template #leading><UiIcon name="key" :size="13" /></template>
          Impersonate
        </UiButton>
        <UiButton variant="secondary">
          <template #leading><UiIcon name="external" :size="13" /></template>
          Open workspace
        </UiButton>
      </template>
    </PageHeader>

    <div class="tabwrap">
      <Tabs v-model="activeTab" :items="tabs" />
    </div>

    <div class="stage">
      <!-- OVERVIEW -->
      <div v-if="activeTab === 'overview'" class="grid">
        <Card>
          <h2>Identity</h2>
          <dl>
            <div class="dl-row"><dt>Slug</dt><dd><Mono>{{ tenant.slug }}</Mono></dd></div>
            <div class="dl-row"><dt>Name</dt><dd>{{ tenant.name }}</dd></div>
            <div class="dl-row"><dt>Status</dt><dd><Badge :tone="STATUS_TONE[tenant.status]" dot>{{ tenant.status }}</Badge></dd></div>
            <div class="dl-row"><dt>Plan</dt><dd><Badge tone="neutral">{{ tenant.plan }}</Badge></dd></div>
            <div class="dl-row"><dt>Domains</dt><dd>
              <Mono v-for="d in tenant.domains" :key="d">{{ d }}</Mono>
              <Mono v-if="!tenant.domains.length" dim>none</Mono>
            </dd></div>
            <div class="dl-row"><dt>Partner</dt><dd>
              <Mono v-if="tenant.partnerId">{{ tenant.partnerId }}</Mono>
              <Mono v-else dim>direct (no partner)</Mono>
            </dd></div>
          </dl>
        </Card>

        <Card>
          <h2>Billing</h2>
          <dl>
            <div class="dl-row"><dt>Company</dt><dd>{{ tenant.billingInfo.companyName || '—' }}</dd></div>
            <div class="dl-row"><dt>VAT</dt><dd><Mono :dim="!tenant.billingInfo.vatId">{{ tenant.billingInfo.vatId || '—' }}</Mono></dd></div>
            <div class="dl-row"><dt>Country</dt><dd><Mono :dim="!tenant.billingInfo.country">{{ tenant.billingInfo.country || '—' }}</Mono></dd></div>
            <div class="dl-row"><dt>Contact</dt><dd><Mono :dim="!tenant.billingInfo.contactEmail">{{ tenant.billingInfo.contactEmail || '—' }}</Mono></dd></div>
          </dl>
        </Card>
      </div>

      <!-- USERS -->
      <div v-else-if="activeTab === 'users'">
        <Card :pad="0">
          <table class="rich">
            <thead>
              <tr>
                <th>User</th><th>Role</th><th>Status</th><th>Last login</th>
              </tr>
            </thead>
            <tbody>
              <tr v-if="(users ?? []).length === 0" class="empty"><td colspan="4"><span class="empty-inner">No users in this tenant yet.</span></td></tr>
              <tr v-for="u in (users ?? [])" :key="u._id">
                <td>
                  <div class="cell-tenant">
                    <div class="cell-name">{{ u.name }}</div>
                    <Mono dim>{{ u.email }}</Mono>
                  </div>
                </td>
                <td>
                  <Badge :tone="u.platformAdmin ? 'accent' : 'neutral'">
                    {{ u.platformAdmin ? 'platform-admin' : u.tenantRole }}
                  </Badge>
                </td>
                <td>
                  <Badge :tone="u.active ? 'ok' : 'bad'" dot>{{ u.active ? 'active' : 'disabled' }}</Badge>
                </td>
                <td><Mono dim>{{ u.lastLoginAt ? new Date(u.lastLoginAt).toISOString().slice(0, 16).replace('T', ' ') : '—' }}</Mono></td>
              </tr>
            </tbody>
          </table>
        </Card>
      </div>

      <!-- RESOURCES (real provisioning state) -->
      <div v-else-if="activeTab === 'resources'" class="grid">
        <Card>
          <div class="card-head">
            <h2>External integrations</h2>
            <UiButton variant="secondary" :disabled="reconcileBusy" @click="reconcile">
              {{ reconcileBusy ? 'Reconciling…' : 'Reconcile now' }}
            </UiButton>
          </div>
          <p v-if="reconcileMessage" class="hint">{{ reconcileMessage }}</p>
          <div class="integrations">
            <div v-for="k in INTEGRATIONS" :key="k" class="integration">
              <div class="integration-head">
                <span class="integration-name">{{ k }}</span>
                <Badge :tone="INTEGRATION_TONE[tenant.provisioningStatus?.[k] ?? 'pending']" dot>
                  {{ tenant.provisioningStatus?.[k] ?? 'pending' }}
                </Badge>
              </div>
              <div v-if="k === 'authentik'" class="integration-meta">
                <Eyebrow>Group ID</Eyebrow>
                <Mono :dim="!tenant.authentikGroupId">{{ tenant.authentikGroupId || 'not provisioned' }}</Mono>
              </div>
              <div v-else-if="k === 'stalwart'" class="integration-meta">
                <Eyebrow>Mail domain</Eyebrow>
                <Mono :dim="!tenant.stalwartDomain">{{ tenant.stalwartDomain || 'not provisioned' }}</Mono>
              </div>
              <div v-else class="integration-meta">
                <Eyebrow>Space ID</Eyebrow>
                <Mono :dim="!tenant.ocisSpaceId">{{ tenant.ocisSpaceId || 'not provisioned' }}</Mono>
              </div>
              <div v-if="tenant.provisioningErrors?.[k]" class="integration-error">
                <Eyebrow>Last error</Eyebrow>
                <Mono>{{ tenant.provisioningErrors[k] }}</Mono>
              </div>
            </div>
          </div>
        </Card>
      </div>

      <!-- BILLING (real · /api/billing/tenants/:slug/invoices) -->
      <div v-else-if="activeTab === 'billing'">
        <Card :pad="0">
          <div class="card-head padded"><h2>Subscription &amp; invoices</h2></div>
          <table class="rich">
            <thead><tr><th>Invoice</th><th>Period</th><th>Amount</th><th>Status</th></tr></thead>
            <tbody>
              <tr v-for="inv in billingInvoices" :key="inv._id">
                <td><Mono>{{ inv.number || inv._id.slice(-8) }}</Mono></td>
                <td><Mono dim>{{ inv.periodEnd || inv.createdAt ? fmtAudit(inv.periodEnd || inv.createdAt || '') : '—' }}</Mono></td>
                <td><Mono>{{ Math.round(inv.amountDue / 100).toLocaleString('da-DK') }} {{ inv.currency }}</Mono></td>
                <td><Badge :tone="invoiceTone(inv.status)" dot>{{ inv.status.replace('_', '-') }}</Badge></td>
              </tr>
              <tr v-if="!billingInvoices.length">
                <td colspan="4" class="empty-cell"><Mono dim>// plan {{ tenant.plan }} · no invoices yet</Mono></td>
              </tr>
            </tbody>
          </table>
        </Card>
      </div>

      <!-- AUDIT (real · /api/audit?tenantSlug) -->
      <div v-else-if="activeTab === 'audit'">
        <Card :pad="0">
          <div class="card-head padded"><h2>Tenant-scoped audit</h2></div>
          <table class="rich">
            <thead><tr><th>When</th><th>Actor</th><th>Action</th><th>Target</th></tr></thead>
            <tbody>
              <tr v-for="a in auditEvents" :key="a._id">
                <td><Mono dim>{{ fmtAudit(a.at) }}</Mono></td>
                <td>{{ a.actorEmail || 'system' }}</td>
                <td><Mono>{{ a.action }}</Mono></td>
                <td><Mono dim>{{ a.resourceName || a.resourceId || '—' }}</Mono></td>
              </tr>
              <tr v-if="!auditEvents.length">
                <td colspan="4" class="empty-cell"><Mono dim>// no audit events for this tenant yet</Mono></td>
              </tr>
            </tbody>
          </table>
        </Card>
      </div>

      <!-- SUPPORT (mock) -->
      <div v-else-if="activeTab === 'support'">
        <Card>
          <div class="card-head"><h2>Support tickets</h2><Badge tone="warn">mock</Badge></div>
          <p class="hint">Support queue ships in a later phase. No real tickets yet.</p>
        </Card>
      </div>

      <!-- DANGER (real) -->
      <div v-else-if="activeTab === 'danger'" class="grid">
        <Card>
          <h2 class="danger">Suspend tenant</h2>
          <p>
            Locks all user logins to this tenant immediately. Mail flow halts, OCIS shares
            become read-only. Reversible via Resume.
          </p>
          <UiButton
            variant="danger"
            :disabled="tenant.status !== 'active'"
            @click="dangerAction = 'suspend'; dangerError = null"
          >Suspend tenant</UiButton>
        </Card>

        <Card>
          <h2>Resume tenant</h2>
          <p>Restores access. Status goes back to active.</p>
          <UiButton
            variant="primary"
            :disabled="tenant.status !== 'suspended'"
            @click="dangerAction = 'resume'; dangerError = null"
          >Resume tenant</UiButton>
        </Card>

        <Card>
          <h2 class="danger">Soft-delete</h2>
          <p>
            Marks the tenant as deleted in Mongo. External resources (Authentik group,
            Stalwart domain, OCIS space) are NOT removed here — that's the next phase.
            Recoverable until the cleanup job runs.
          </p>
          <UiButton
            variant="danger"
            :disabled="tenant.status === 'deleted'"
            @click="dangerAction = 'delete'; dangerError = null"
          >Soft-delete tenant</UiButton>
        </Card>
      </div>
    </div>

    <ConfirmDialog
      :open="dangerAction !== null"
      :eyebrow="`Tenant · ${tenant.slug}`"
      :title="dangerAction === 'delete' ? 'Soft-delete this tenant?' : dangerAction === 'suspend' ? 'Suspend this tenant?' : 'Resume this tenant?'"
      :confirm-label="dangerAction === 'delete' ? 'Delete' : dangerAction === 'suspend' ? 'Suspend' : 'Resume'"
      :tone="dangerAction === 'resume' ? 'primary' : 'danger'"
      :busy="dangerBusy"
      @close="dangerAction = null"
      @confirm="confirmDanger"
    >
      <p v-if="dangerAction === 'suspend'">
        All <strong>{{ tenant.name }}</strong> users will lose access on their next request.
        You can resume at any time — no data is removed.
      </p>
      <p v-else-if="dangerAction === 'resume'">
        Lift the suspension on <strong>{{ tenant.name }}</strong>. Logins resume immediately.
      </p>
      <p v-else>
        Mark <strong>{{ tenant.name }}</strong> as deleted. Their data stays in Mongo until
        the cleanup job runs; external resources stay untouched.
      </p>
      <p v-if="dangerError" class="danger-err">{{ dangerError }}</p>
    </ConfirmDialog>
  </div>
</template>

<style scoped>
.tabwrap { padding: 0 40px; }

.stage {
  padding: 24px 40px 64px 40px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
  gap: 16px;
}

h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 16px;
  letter-spacing: -0.01em;
  margin: 0 0 16px 0;
}
h2.danger { color: var(--bad); }

p {
  margin: 0 0 14px 0;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.55;
}
p.hint { font-size: 12px; color: var(--text-mute); margin-bottom: 0; }
.danger-err { color: var(--bad); font-family: var(--font-mono); font-size: 12px; }

dl { display: flex; flex-direction: column; gap: 10px; }
dl.mt { margin-top: 14px; }
.dl-row {
  display: grid;
  grid-template-columns: 120px 1fr;
  gap: 12px;
  font-size: 13px;
}
dt {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-mute);
  align-self: center;
}
dd {
  margin: 0;
  color: var(--text);
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}
.card-head h2 { margin: 0; }
.card-head.padded { padding: 20px 24px 0 24px; }

.integrations {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 12px;
}

.integration {
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
}
.integration-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}
.integration-name {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
}
.integration-meta {
  display: flex;
  gap: 12px;
  align-items: center;
  font-size: 12px;
}
.integration-meta > :first-child { width: 80px; flex-shrink: 0; }

.integration-error {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 4px;
  color: var(--bad);
}

table.rich {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
table.rich thead tr { border-bottom: 1px solid var(--border); }
table.rich th {
  padding: 12px 16px;
  text-align: left;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-mute);
}
table.rich tbody tr { border-bottom: 1px solid var(--border); }
table.rich tbody tr:last-child { border-bottom: none; }
table.rich td { padding: 14px 16px; }
table.rich .empty td { padding: 36px 16px; text-align: center; }
.empty-inner { color: var(--text-mute); font-size: 13px; }

.cell-tenant { display: flex; flex-direction: column; gap: 2px; }
.cell-name { font-weight: 500; }
</style>
