<!-- SPEC: PJ2026-010405 云端控制台 / Users. -->
<!-- Implementation reference: draft-2026-07-13-p0-cloud-console. -->
<script setup lang="ts">
import { Grid2X2, List, Rows3, Rows4 } from "lucide-vue-next";
import AsyncBoundary from "@/components/common/AsyncBoundary.vue";
import BaseDrawer from "@/components/common/BaseDrawer.vue";
import DataGrid from "@/components/common/DataGrid.vue";
import EmptyState from "@/components/common/EmptyState.vue";
import Pagination from "@/components/common/Pagination.vue";
import OperationsWorkspace from "@/components/console/OperationsWorkspace.vue";
import ViewModeSwitch from "@/components/console/ViewModeSwitch.vue";
import PageCommandBar from "@/components/layout/PageCommandBar.vue";
import SectionFrame from "@/components/layout/SectionFrame.vue";
import StatusStrip from "@/components/layout/StatusStrip.vue";
import UserDirectoryCollection from "@/components/users/UserDirectoryCollection.vue";
import UserDirectoryIndex from "@/components/users/UserDirectoryIndex.vue";
import UserAccountInspector from "@/components/users/UserAccountInspector.vue";
import { useUsersWorkspace } from "@/composables/admin/useUsersWorkspace";

const {
  users, plans, selectedUserId, loading, detailLoading, error, mutationError,
  pending, page, pageSize, total, createOpen, filters, createForm, editForm,
  creditForm, selectedSummary, selectedUser, selectedEntitlements, ledgerRows,
  apiKeys, reservations, viewMode, density, detailTab, asyncState, statusItems,
  loadUsers, applyFilters, setPage, selectUser, closeInspector, createUser, saveUser,
  setUserStatus, adjustCredits, userColumns, userKey, formatNumber,
  auditTab, auditLoading, auditError, auditUsageRows, auditLedgerRows,
  auditPage, auditPageSize, auditTotal, auditFilters, loadAudit, setAuditTab, setAuditPage,
  downloadAudit, usageColumns, ledgerColumns, auditKey, formatSigned, formatDate,
  metadataPreview,
} = useUsersWorkspace();
</script>

<template>
  <section class="route-stack user-operations-page">
    <PageCommandBar
      eyebrow="Admin"
      title="身份运营工作区"
      description="用户索引、身份主面与账务 Inspector 共享同一服务端分页数据集。"
    >
      <template #actions
        ><ViewModeSwitch
          v-model="viewMode"
          :options="[
            { value: 'list', label: '紧凑列表', icon: List },
            { value: 'grid', label: '实体网格', icon: Grid2X2 },
          ]"
        /><ViewModeSwitch
          v-model="density"
          :options="[
            { value: 'comfortable', label: '舒适密度', icon: Rows4 },
            { value: 'compact', label: '紧凑密度', icon: Rows3 },
          ]"
          label="用户集合密度"
        /><button class="table-action" type="button" @click="createOpen = true">
          创建用户
        </button></template
      >
    </PageCommandBar>
    <AsyncBoundary
      :state="asyncState"
      :has-content="Boolean(users.length)"
      label="加载身份运营"
      @retry="loadUsers"
    >
      <template #error
        ><EmptyState
          title="身份运营加载失败"
          :description="error || '请求未完成'"
          action-label="重试"
          @action="loadUsers"
      /></template>
      <StatusStrip :items="statusItems" />
      <p v-if="mutationError" class="form-error">{{ mutationError }}</p>
      <OperationsWorkspace
        class="user-operations"
        label="用户身份运营"
        :inspector-open="Boolean(selectedUserId)"
      >
        <template #index><UserDirectoryIndex v-model:search="filters.search" v-model:status="filters.status" v-model:role="filters.role" :users="users" :selected-id="selectedUserId" :page="page" :page-size="pageSize" :total="total" @select="selectUser" @apply="applyFilters" @page="setPage" /></template>

        <div class="user-main-stack">
          <UserDirectoryCollection :users="users" :selected-id="selectedUserId" :view="viewMode" :density="density" :pending-id="pending?.startsWith('status:') ? pending.slice(7) : null" @select="selectUser" @status="setUserStatus" />

          <SectionFrame
            title="全局 Usage / Ledger"
            description="保留旧页全部筛选、服务端分页、错误/partial 状态与 CSV export。"
            :body-padding="false"
          >
            <div class="audit-command-row">
              <div role="tablist" aria-label="运营审计数据">
                <button
                  type="button"
                  role="tab"
                  :aria-selected="auditTab === 'usage'"
                  @click="setAuditTab('usage')"
                >
                  Usage</button
                ><button
                  type="button"
                  role="tab"
                  :aria-selected="auditTab === 'ledger'"
                  @click="setAuditTab('ledger')"
                >
                  Ledger
                </button>
              </div>
              <button class="table-action" type="button" @click="downloadAudit">
                CSV / Export
              </button>
            </div>
            <div class="audit-filter-grid">
              <input
                v-model="auditFilters.search"
                class="input"
                placeholder="搜索记录或原因"
                @keyup.enter="() => loadAudit()"
              /><input
                v-model="auditFilters.userId"
                class="input"
                placeholder="user id"
                @keyup.enter="() => loadAudit()"
              /><input
                v-if="auditTab === 'usage'"
                v-model="auditFilters.serviceId"
                class="input"
                placeholder="service"
                @keyup.enter="() => loadAudit()"
              /><input
                v-if="auditTab === 'usage'"
                v-model="auditFilters.resourceType"
                class="input"
                placeholder="resource"
                @keyup.enter="() => loadAudit()"
              /><input
                v-if="auditTab === 'usage'"
                v-model="auditFilters.apiKeyId"
                class="input"
                placeholder="api key id"
                @keyup.enter="() => loadAudit()"
              /><input
                v-if="auditTab === 'ledger'"
                v-model="auditFilters.kind"
                class="input"
                placeholder="kind"
                @keyup.enter="() => loadAudit()"
              /><input
                v-if="auditTab === 'ledger'"
                v-model="auditFilters.source"
                class="input"
                placeholder="source"
                @keyup.enter="() => loadAudit()"
              /><input
                v-model="auditFilters.status"
                class="input"
                placeholder="status"
                @keyup.enter="() => loadAudit()"
              /><input
                v-model="auditFilters.idempotencyKey"
                class="input"
                placeholder="idempotency key"
                @keyup.enter="() => loadAudit()"
              /><input
                v-model="auditFilters.from"
                class="input"
                type="datetime-local"
                @change="() => loadAudit()"
              /><input
                v-model="auditFilters.to"
                class="input"
                type="datetime-local"
                @change="() => loadAudit()"
              /><button
                class="table-action"
                type="button"
                @click="
                  auditPage = 1;
                  loadAudit();
                "
              >
                应用筛选
              </button>
            </div>
            <p v-if="auditError" class="form-error">{{ auditError }}</p>
            <p v-if="auditLoading" class="muted-box">审计加载中…</p>
            <DataGrid
              v-else-if="auditTab === 'usage'"
              :columns="usageColumns"
              :rows="auditUsageRows"
              :row-key="auditKey"
              :interactive="false"
              aria-label="全局 Usage"
            >
              <template #cell-time="{ row }">{{
                formatDate(row.createdAt)
              }}</template
              ><template #cell-user="{ row }"
                ><code>{{ row.userId }}</code
                ><small>{{ row.username || row.email }}</small></template
              ><template #cell-service="{ row }"
                ><code>{{ row.serviceId }}</code></template
              ><template #cell-resource="{ row }">{{
                row.resourceType || row.id
              }}</template
              ><template #cell-credits="{ row }">{{
                formatNumber(row.credits)
              }}</template
              ><template #cell-status="{ row }">{{ row.status }}</template
              ><template #cell-metadata="{ row }">{{
                metadataPreview(row.metadata)
              }}</template>
            </DataGrid>
            <DataGrid
              v-else
              :columns="ledgerColumns"
              :rows="auditLedgerRows"
              :row-key="auditKey"
              :interactive="false"
              aria-label="全局 Ledger"
            >
              <template #cell-time="{ row }">{{
                formatDate(row.createdAt)
              }}</template
              ><template #cell-user="{ row }"
                ><code>{{ row.userId }}</code
                ><small>{{ row.username || row.email }}</small></template
              ><template #cell-action="{ row }"
                >{{ row.kind }} · {{ row.reason }}</template
              ><template #cell-delta="{ row }">{{
                formatSigned(row.deltaCredits)
              }}</template
              ><template #cell-balance="{ row }"
                >{{ formatNumber(row.balanceBefore) }} →
                {{ formatNumber(row.balanceAfter) }}</template
              ><template #cell-operator="{ row }">{{
                row.operatorUsername || row.operatorUserId || row.source
              }}</template
              ><template #cell-idempotency="{ row }"
                ><code>{{ row.idempotencyKey || "-" }}</code></template
              >
            </DataGrid>
            <Pagination
              :page="auditPage"
              :page-size="auditPageSize"
              :total="auditTotal"
              @update:page="setAuditPage"
            />
          </SectionFrame>
        </div>

        <template #inspector><UserAccountInspector v-if="selectedUserId" :user-id="selectedUserId" :user="selectedUser" :summary="selectedSummary" :plans="plans" :tab="detailTab" :loading="detailLoading" :error="mutationError" :pending="pending" :edit-form="editForm" :credit-form="creditForm" :entitlements="selectedEntitlements" :api-keys="apiKeys" :reservations="reservations" :ledger-rows="ledgerRows" @close="closeInspector" @tab="detailTab = $event" @save="saveUser" @adjust="adjustCredits" /></template>
      </OperationsWorkspace>
      <BaseDrawer
        :open="createOpen"
        title="创建用户"
        description="写入 user-billing authority"
        :busy="pending === 'create'"
        @close="createOpen = false"
        ><div class="form-grid two-col">
          <label
            >邮箱<input
              v-model="createForm.email"
              class="input"
              type="email" /></label
          ><label
            >用户名<input v-model="createForm.username" class="input" /></label
          ><label
            >显示名<input
              v-model="createForm.displayName"
              class="input" /></label
          ><label
            >密码<input
              v-model="createForm.password"
              class="input"
              type="password" /></label
          ><label
            >初始 credits<input
              v-model.number="createForm.initialCredits"
              class="input"
              type="number" /></label
          ><label
            >角色<select v-model="createForm.role" class="input">
              <option value="user">user</option>
              <option value="admin">admin</option>
            </select></label
          ><label
            >状态<select v-model="createForm.status" class="input">
              <option value="active">active</option>
              <option value="pending">pending</option>
              <option value="disabled">disabled</option>
            </select></label
          >
        </div>
        <template #footer
          ><button
            class="table-action"
            type="button"
            @click="createOpen = false"
          >
            取消</button
          ><button
            class="btn btn-primary"
            type="button"
            :disabled="pending === 'create'"
            @click="createUser"
          >
            创建
          </button></template
        ></BaseDrawer
      >
    </AsyncBoundary>
  </section>
</template>

<style src="./UsersView.css"></style>
