<template>
  <view class="page">
    <view class="header">
      <text class="title">消费账单</text>
    </view>

    <!-- 汇总卡片 -->
    <view class="summary-card">
      <view class="summary-item">
        <text class="summary-value">¥{{ summary.totalCost }}</text>
        <text class="summary-label">总费用</text>
      </view>
      <view class="summary-divider" />
      <view class="summary-item">
        <text class="summary-value">{{ summary.totalCalls }}</text>
        <text class="summary-label">总调用次数</text>
      </view>
      <view class="summary-divider" />
      <view class="summary-item">
        <text class="summary-value">{{ summary.totalTokens }}</text>
        <text class="summary-label">总Token消耗</text>
      </view>
    </view>

    <!-- 分类统计 -->
    <view class="type-stats" v-if="summary.byType.length">
      <view class="type-item" v-for="t in summary.byType" :key="t.type">
        <text class="type-name">{{ typeLabel(t.type) }}</text>
        <view class="type-data">
          <text class="type-count">{{ t.count }}次</text>
          <text class="type-cost">¥{{ t.cost.toFixed(4) }}</text>
        </view>
      </view>
    </view>

    <!-- 明细列表 -->
    <view class="section-title">调用明细</view>
    <view class="record-list">
      <view class="record-card" v-for="r in records" :key="r.id">
        <view class="record-top">
          <text :class="['call-badge', r.callType.startsWith('llm') ? 'badge-llm' : 'badge-tts']">
            {{ typeLabel(r.callType) }}
          </text>
          <text class="record-time">{{ formatTime(r.time) }}</text>
        </view>
        <view class="record-info">
          <text class="record-model">{{ r.model }}</text>
        </view>
        <view class="record-tokens" v-if="r.inputTokens || r.outputTokens">
          <text v-if="r.callType.startsWith('llm')">
            in: {{ r.inputTokens }}tk / out: {{ r.outputTokens }}tk
          </text>
          <text v-else>
            字符: {{ r.textLen || r.outputTokens }}
          </text>
        </view>
        <view class="record-bottom">
          <text class="record-cost">¥{{ r.cost }}</text>
          <text class="record-dur" v-if="r.duration">{{ (r.duration / 1000).toFixed(1) }}s</text>
          <text :class="['record-status', r.success ? 'status-ok' : 'status-fail']">
            {{ r.success ? '✓' : '✗' }}
          </text>
        </view>
      </view>
    </view>

    <view class="empty" v-if="loading">
      <text>加载中...</text>
    </view>
    <view class="empty" v-else-if="!records.length">
      <text>暂无消费记录</text>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { request } from '@/utils/request';

interface LogRecord {
  id: number; callType: string; provider: string; model: string;
  textLen: number; inputTokens: number; outputTokens: number;
  cost: number; duration: number; success: boolean; bookId: number; time: string;
}

const records = ref<LogRecord[]>([]);
const loading = ref(true);

const summary = ref({
  totalCost: '0',
  totalCalls: 0,
  totalTokens: 0,
  byType: [] as Array<{ type: string; count: number; cost: number; inputTokens: number; outputTokens: number }>,
});

function typeLabel(type: string): string {
  const map: Record<string, string> = {
    llm_chat: '文本生成', llm_tools: '工具调用',
    tts_synthesize: '语音合成', tts_create: 'TTS创建',
    tts_poll: 'TTS查询', tts_task_completed: 'TTS完成',
    tts_task_failed: 'TTS失败',
  };
  return map[type] || type;
}

function formatTime(t: string): string {
  if (!t) return '';
  return t.replace('T', ' ').substring(0, 19);
}

async function loadBilling() {
  try {
    const data = await request('/subscription/billing/summary') as any;
    // request() 已解包 result.data，data 直接是 {totalCalls, records, ...}
    if (data?.records) {
      records.value = (data.records || []).map((r: any) => ({ ...r, cost: r.cost || 0 }));
      summary.value = {
        totalCost: (data.totalCost || 0).toFixed(4),
        totalCalls: data.totalCalls || 0,
        totalTokens: (data.totalInputTokens || 0) + (data.totalOutputTokens || 0),
        byType: data.byType || [],
      };
    }
  } catch (e) {
    console.error('加载账单失败', e);
  } finally {
    loading.value = false;
  }
}
onMounted(loadBilling);
</script>

<style scoped>
.page { min-height: 100vh; background: #f5f5f5; padding-bottom: 30rpx; }
.header { padding: 30rpx; display: flex; justify-content: space-between; align-items: center; }
.title { font-size: 36rpx; font-weight: bold; color: #333; }

.summary-card {
  margin: 0 24rpx 20rpx; padding: 30rpx; border-radius: 16rpx;
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  display: flex; justify-content: space-around;
}
.summary-item { display: flex; flex-direction: column; align-items: center; }
.summary-value { font-size: 40rpx; font-weight: bold; color: #fff; }
.summary-label { font-size: 22rpx; color: rgba(255,255,255,0.7); margin-top: 6rpx; }
.summary-divider { width: 1px; background: rgba(255,255,255,0.2); }

.type-stats { margin: 0 24rpx 20rpx; padding: 20rpx; background: #fff; border-radius: 12rpx; }
.type-item { display: flex; justify-content: space-between; align-items: center; padding: 12rpx 0; border-bottom: 1px solid #f0f0f0; }
.type-item:last-child { border-bottom: none; }
.type-name { font-size: 28rpx; color: #333; }
.type-data { display: flex; gap: 20rpx; align-items: center; }
.type-count { font-size: 24rpx; color: #999; }
.type-cost { font-size: 28rpx; font-weight: bold; color: #6366f1; }

.section-title { margin: 24rpx 24rpx 16rpx; font-size: 28rpx; font-weight: bold; color: #333; }

.record-list { margin: 0 24rpx; }
.record-card { background: #fff; border-radius: 12rpx; padding: 20rpx; margin-bottom: 12rpx; }
.record-top { display: flex; justify-content: space-between; align-items: center; }
.call-badge { font-size: 22rpx; padding: 4rpx 12rpx; border-radius: 6rpx; color: #fff; }
.badge-llm { background: #3b82f6; }
.badge-tts { background: #10b981; }
.record-time { font-size: 22rpx; color: #999; }
.record-info { margin-top: 8rpx; }
.record-model { font-size: 26rpx; color: #333; }
.record-tokens { margin-top: 6rpx; }
.record-tokens text { font-size: 22rpx; color: #888; }
.record-bottom { margin-top: 10rpx; display: flex; align-items: center; gap: 16rpx; }
.record-cost { font-size: 30rpx; font-weight: bold; color: #f59e0b; }
.record-dur { font-size: 22rpx; color: #aaa; }
.record-status { font-size: 24rpx; font-weight: bold; }
.status-ok { color: #10b981; }
.status-fail { color: #ef4444; }
.empty { text-align: center; padding: 60rpx; color: #999; font-size: 28rpx; }
</style>
