<!-- SPEC: PJ2026-010405 云端控制台 / User Billing. -->
<!-- Implementation reference: draft-2026-07-13-p0-cloud-console. -->
<script setup lang="ts">
import { computed, reactive, watch } from "vue";
import BaseDialog from "@/components/common/BaseDialog.vue";
import DataGrid from "@/components/common/DataGrid.vue";
import type { DataGridColumn } from "@/components/common/DataGrid.vue";
import SectionFrame from "@/components/layout/SectionFrame.vue";
import StatusStrip from "@/components/layout/StatusStrip.vue";
import type { PaymentSummaryResponse, RedeemResponse, ResourceEntitlementSummary, SubscriptionSummaryResponse, UsageSummary } from "@/types";

const props = defineProps<{
  summary: UsageSummary | null;
  subscription: SubscriptionSummaryResponse | null;
  payment: PaymentSummaryResponse | null;
  pending: boolean;
  redeemError: string | null;
  redeemResult: RedeemResponse | null;
}>();
const redeemOpen = defineModel<boolean>("redeemOpen", { required: true });
const emit = defineEmits<{ redeem: [payload: { code: string; idempotencyKey?: string }] }>();
const form = reactive({ code: "", idempotencyKey: "" });
const entitlementColumns: DataGridColumn[] = [{ key: "resource", label: "Resource" }, { key: "status", label: "Status" }, { key: "monthly", label: "Monthly" }, { key: "concurrent", label: "Concurrent" }, { key: "rpm", label: "RPM" }];
const credits = computed(() => props.summary?.credits ?? {});
const entitlements = computed(() => props.subscription?.entitlements ?? props.summary?.entitlements ?? []);
const paymentProvider = computed(() => props.payment?.provider ?? props.subscription?.payment ?? null);
const providerStatus = computed(() => paymentProvider.value?.status ?? "contract-unavailable");
const statusItems = computed(() => [
  { id: "authority", label: "Authority", value: "PK01 user-billing" },
  { id: "plan", label: "Plan", value: props.subscription?.plan?.displayName || props.subscription?.planId || props.summary?.planId || "default" },
  { id: "payment", label: "Payment", value: providerStatus.value, tone: providerStatus.value === "ready" ? "ok" as const : "warn" as const },
  { id: "entitlements", label: "Entitlements", value: entitlements.value.length }
]);

watch(() => props.redeemResult, (result) => { if (result?.result) form.code = ""; });
function formatNumber(value: unknown): string { const number = Number(value ?? 0); return Number.isFinite(number) ? new Intl.NumberFormat("zh-CN").format(number) : "0"; }
function entitlementKey(row: ResourceEntitlementSummary): string { return row.id || row.resourceType || "entitlement"; }
function submit(): void { const code = form.code.trim(); if (!code || props.pending) return; emit("redeem", { code, idempotencyKey: form.idempotencyKey.trim() || undefined }); }
</script>

<template>
  <div class="user-billing-workspace">
    <StatusStrip :items="statusItems" label="用户账务状态" live="polite" />
    <div class="overview-grid usage-metrics">
      <article class="metric-card"><span>可用 credit</span><strong>{{ formatNumber(credits.available) }}</strong></article>
      <article class="metric-card"><span>余额</span><strong>{{ formatNumber(credits.balance) }}</strong></article>
      <article class="metric-card"><span>已预留</span><strong>{{ formatNumber(credits.reserved) }}</strong></article>
      <article class="metric-card"><span>Payment</span><strong>{{ providerStatus }}</strong></article>
    </div>

    <SectionFrame title="订阅资源授权" description="来自 subscription/usage typed read model。" :body-padding="false">
      <template #actions><button class="table-action primary" type="button" @click="redeemOpen = true">兑换充值码</button></template>
      <DataGrid :columns="entitlementColumns" :rows="entitlements" :row-key="entitlementKey" :interactive="false" density="compact" empty-text="当前 plan 没有 entitlement 记录。" aria-label="订阅资源授权">
        <template #cell-resource="{ row }"><code>{{ (row as ResourceEntitlementSummary).resourceType }}</code></template>
        <template #cell-status="{ row }"><span class="status-pill" :data-status="(row as ResourceEntitlementSummary).enabled ? 'active' : 'disabled'">{{ (row as ResourceEntitlementSummary).enabled ? 'enabled' : 'disabled' }}</span></template>
        <template #cell-monthly="{ row }">{{ formatNumber((row as ResourceEntitlementSummary).monthlyUsageCredits) }} / {{ (row as ResourceEntitlementSummary).monthlyQuotaUnlimited ? 'unlimited' : formatNumber((row as ResourceEntitlementSummary).monthlyQuotaCredits) }}</template>
        <template #cell-concurrent="{ row }">{{ formatNumber((row as ResourceEntitlementSummary).activeReservations) }} / {{ (row as ResourceEntitlementSummary).concurrencyUnlimited ? 'unlimited' : formatNumber((row as ResourceEntitlementSummary).maxConcurrentReservations) }}</template>
        <template #cell-rpm="{ row }">{{ formatNumber((row as ResourceEntitlementSummary).rpmUsed) }} / {{ (row as ResourceEntitlementSummary).rpmUnlimited ? 'unlimited' : formatNumber((row as ResourceEntitlementSummary).rpmLimit) }}</template>
      </DataGrid>
    </SectionFrame>

    <SectionFrame title="支付 Provider" :description="paymentProvider?.message || '支付摘要契约未返回 provider 状态；当前不推断配置状态。'" tone="inset">
      <span class="status-pill" :data-status="providerStatus">{{ providerStatus }}</span>
    </SectionFrame>

    <BaseDialog :open="redeemOpen" title="兑换充值码" description="提交到 user-billing；幂等键仅用于避免重复兑换。" @close="redeemOpen = false">
      <form class="form-grid" @submit.prevent="submit">
        <label>Code<input v-model="form.code" class="input" autocomplete="one-time-code" placeholder="hwl_redeem_..." /></label>
        <label>Idempotency key<input v-model="form.idempotencyKey" class="input" placeholder="可选；重复提交时防重" /></label>
        <p v-if="redeemError" class="form-error">{{ redeemError }}</p>
        <p v-if="redeemResult?.result" class="stale-warning">已兑换 {{ formatNumber(redeemResult.result.creditAmount) }} credits，余额 {{ formatNumber(redeemResult.result.balanceBefore) }} → {{ formatNumber(redeemResult.result.balanceAfter) }}。</p>
      </form>
      <template #footer><button class="table-action" type="button" @click="redeemOpen = false">关闭</button><button class="table-action primary" type="button" :disabled="pending || !form.code.trim()" @click="submit">{{ pending ? '兑换中' : '兑换' }}</button></template>
    </BaseDialog>
  </div>
</template>

<style scoped>.user-billing-workspace { display: grid; gap: 12px; min-width: 0; }</style>
