<script setup lang="ts">
import { CalendarDays, CheckCircle2, CircleMinus, LogOut, PackageCheck, Sparkles } from "@lucide/vue";
import { computed, ref } from "vue";

import type { PeriodicReport, PracticeReviewResult, ShareDraft, TeacherHelpCard, UserProfile } from "../types/api";
import AppDialog from "./AppDialog.vue";

type CenterSection = "overview" | "review" | "records";

const props = defineProps<{
  user: UserProfile;
  initialSection: CenterSection;
  loading: boolean;
  practiceReview: PracticeReviewResult | null;
  reports: PeriodicReport[];
  helpCards: TeacherHelpCard[];
  shareDrafts: ShareDraft[];
}>();

defineEmits<{
  close: [];
  logout: [];
}>();

const activeSection = ref<CenterSection>(props.initialSection);
const entitlement = computed(() => props.user.entitlement);
const displayName = computed(() => props.user.nickname?.trim() || props.user.name);
const nameInitial = computed(() => displayName.value.slice(0, 1));
const maskedPhone = computed(() => props.user.phone.replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2"));
const topicUsed = computed(() => entitlement.value?.monthlyTopicUsed ?? 0);
const topicLimit = computed(() => entitlement.value?.monthlyTopicLimit ?? null);
const topicRemaining = computed(() => entitlement.value?.monthlyTopicRemaining ?? null);
const topicPercent = computed(() => usagePercent(topicUsed.value, topicLimit.value));
const dailyRemaining = computed(() => Math.max(0, props.user.dailyLimit - props.user.todayUsed));
const dailyPercent = computed(() => usagePercent(props.user.todayUsed, props.user.dailyLimit));

const capabilities = computed(() => [
  { label: "知识问答", enabled: true },
  { label: "近期实修回顾", enabled: Boolean(entitlement.value?.enableGrowthProfile) },
  { label: "周期实修回顾", enabled: Boolean(entitlement.value?.enablePeriodicReports) },
  { label: "老师求助卡", enabled: Boolean(entitlement.value?.allowHelpCard) },
  { label: "班级分享稿", enabled: Boolean(entitlement.value?.allowShareDraft) },
]);

function usagePercent(used: number, limit: number | null) {
  if (limit === null || limit <= 0) return 0;
  return Math.min(100, Math.max(0, Math.round((used / limit) * 100)));
}

function formatDate(value?: string | null) {
  if (!value) return "长期有效";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleDateString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit" });
}

function settlementStatusLabel(status: string) {
  return {
    pending: "等待整理",
    running: "整理中",
    success: "已完成",
    fallback: "已完成",
    failed: "整理失败",
  }[status] || status;
}
</script>

<template>
  <AppDialog title="个人中心" labelled-by="personal-center-title" @close="$emit('close')">
    <section class="personal-center" :aria-busy="loading">
      <header class="member-card">
        <div class="member-avatar" aria-hidden="true">{{ nameInitial }}</div>
        <div class="member-copy">
          <strong>{{ displayName }}</strong>
          <span>{{ maskedPhone }}</span>
        </div>
        <span class="member-plan">{{ entitlement?.name || '基础服务' }}</span>
      </header>

      <nav class="center-tabs" role="tablist" aria-label="个人中心栏目">
        <button type="button" role="tab" :aria-selected="activeSection === 'overview'" @click="activeSection = 'overview'">账号权益</button>
        <button type="button" role="tab" :aria-selected="activeSection === 'review'" @click="activeSection = 'review'">实修回顾</button>
        <button type="button" role="tab" :aria-selected="activeSection === 'records'" @click="activeSection = 'records'">我的卡片</button>
      </nav>

      <div v-if="activeSection === 'overview'" class="center-section">
        <aside v-if="entitlement?.lifecycleStatus === 'expired_fallback'" class="entitlement-notice expired">
          <strong>权益已平稳切换</strong>
          <span>原“{{ entitlement.previousPlanName || '专属权益' }}”已于 {{ formatDate(entitlement.previousExpiredAt) }} 到期，当前已自动切换为“{{ entitlement.name }}”。已有聊天、实修回顾和卡片记录仍会保留。</span>
        </aside>
        <aside v-else-if="entitlement?.lifecycleStatus === 'expiring_7' || entitlement?.lifecycleStatus === 'expiring_30'" class="entitlement-notice">
          <strong>权益即将到期</strong>
          <span>当前权益有效至 {{ formatDate(entitlement.expiredAt) }}。如需继续使用，可提前联系运营老师确认续期。</span>
        </aside>
        <article class="plan-card">
          <div class="section-heading">
            <PackageCheck :size="18" aria-hidden="true" />
            <div>
              <span>当前权益</span>
              <strong>{{ entitlement?.name || '基础服务' }}</strong>
            </div>
          </div>
          <p>{{ entitlement?.description || '提供当前账号可使用的问答与陪伴能力。' }}</p>
          <dl class="plan-meta">
            <div>
              <dt>生效时间</dt>
              <dd>{{ entitlement?.effectiveAt ? formatDate(entitlement.effectiveAt) : '当前已生效' }}</dd>
            </div>
            <div>
              <dt>有效期至</dt>
              <dd>{{ formatDate(entitlement?.expiredAt) }}</dd>
            </div>
          </dl>
        </article>

        <section class="usage-section">
          <h3>使用情况</h3>
          <article class="usage-card">
            <div>
              <span>本月主题</span>
              <strong>{{ topicLimit === null ? `${topicUsed} 个 · 不限` : `${topicUsed}/${topicLimit} 个` }}</strong>
            </div>
            <div class="usage-track" aria-hidden="true"><i :style="{ width: `${topicPercent}%` }" /></div>
            <small>{{ topicRemaining === null ? '当前权益不限制本月主题数量' : `本月还可开启 ${topicRemaining} 个主题` }}</small>
          </article>
          <article class="usage-card">
            <div>
              <span>今日问答</span>
              <strong>{{ user.todayUsed }}/{{ user.dailyLimit }} 次</strong>
            </div>
            <div class="usage-track" aria-hidden="true"><i :style="{ width: `${dailyPercent}%` }" /></div>
            <small>今日还可使用 {{ dailyRemaining }} 次，次日自动恢复</small>
          </article>
        </section>

        <section class="capability-section">
          <h3>当前可用能力</h3>
          <ul>
            <li v-for="item in capabilities" :key="item.label" :class="{ unavailable: !item.enabled }">
              <CheckCircle2 v-if="item.enabled" :size="17" aria-hidden="true" />
              <CircleMinus v-else :size="17" aria-hidden="true" />
              <span>{{ item.label }}</span>
              <small>{{ item.enabled ? '已包含' : '当前权益未包含' }}</small>
            </li>
          </ul>
        </section>
      </div>

      <div v-else-if="activeSection === 'review'" class="center-section review-section">
        <p v-if="loading" class="center-empty">正在加载近期回顾...</p>
        <template v-else-if="practiceReview?.profile">
          <article class="review-card primary-review">
            <div class="section-heading">
              <Sparkles :size="18" aria-hidden="true" />
              <strong>近期实修回顾</strong>
            </div>
            <p>{{ practiceReview.profile.reviewText }}</p>
            <div v-if="practiceReview.profile.currentFocus" class="current-focus">
              <span>近期关注</span>
              <p>{{ practiceReview.profile.currentFocus }}</p>
            </div>
          </article>
        </template>
        <p v-else-if="!entitlement?.enableGrowthProfile" class="center-empty">当前权益未包含近期实修回顾，你仍然可以正常使用知识问答和当前已开放的其他能力。</p>
        <p v-else class="center-empty">还没有近期回顾。完成一次主题对话并沉淀后，这里会帮助你简单回看近期谈到的内容。</p>

        <section v-if="practiceReview?.recentSummaries.length" class="record-group">
          <h3>最近谈到的主题</h3>
          <article v-for="item in practiceReview.recentSummaries" :key="item.id" class="compact-record">
            <time>{{ formatDate(item.generatedAt) }} · {{ settlementStatusLabel(item.status) }}</time>
            <p v-if="item.status === 'success' || item.status === 'fallback'">{{ item.summary }}</p>
            <p v-else-if="item.status === 'failed'">本次记录暂时整理失败，对话内容仍已保留。</p>
            <p v-else>本次记录正在后台整理，可以继续使用其他功能。</p>
          </article>
        </section>

        <section v-if="reports.length" class="record-group">
          <h3>周期实修回顾</h3>
          <details v-for="item in reports" :key="item.id" class="report-record">
            <summary>
              <CalendarDays :size="16" aria-hidden="true" />
              <span>{{ item.title }}</span>
              <small>{{ item.reportTypeLabel }}</small>
            </summary>
            <time>{{ formatDate(item.periodStart) }} 至 {{ formatDate(item.periodEnd) }}</time>
            <pre>{{ item.content }}</pre>
          </details>
        </section>
      </div>

      <div v-else class="center-section records-section">
        <section class="record-group">
          <h3>老师求助卡</h3>
          <article v-for="item in helpCards" :key="`help-${item.id}`" class="compact-record">
            <time>{{ formatDate(item.createdAt) }} · {{ item.copied ? '已复制' : '未复制' }}</time>
            <p>{{ item.content.slice(0, 160) }}{{ item.content.length > 160 ? '…' : '' }}</p>
          </article>
          <p v-if="!loading && !helpCards.length" class="center-empty small">还没有生成过求助卡。</p>
        </section>
        <section class="record-group">
          <h3>班级分享稿</h3>
          <article v-for="item in shareDrafts" :key="`share-${item.id}`" class="compact-record">
            <time>{{ formatDate(item.createdAt) }} · {{ item.copied ? '已复制' : '未复制' }}</time>
            <p>{{ item.content.slice(0, 160) }}{{ item.content.length > 160 ? '…' : '' }}</p>
          </article>
          <p v-if="!loading && !shareDrafts.length" class="center-empty small">还没有生成过分享稿。</p>
        </section>
      </div>
    </section>

    <template #footer>
      <div class="personal-center-footer">
        <button type="button" class="center-logout" @click="$emit('logout')">
          <LogOut :size="17" aria-hidden="true" />
          退出当前账号
        </button>
        <button type="button" class="dialog-primary center-done" @click="$emit('close')">完成</button>
      </div>
    </template>
  </AppDialog>
</template>

<style scoped>
.personal-center { display: grid; gap: 16px; color: var(--chat-text); }
.member-card { display: grid; grid-template-columns: 46px minmax(0, 1fr) auto; align-items: center; gap: 11px; }
.member-avatar { width: 46px; height: 46px; display: grid; place-items: center; border-radius: 15px; background: linear-gradient(145deg, #dceee7, #edf7f3); color: var(--chat-brand-dark); font-size: 19px; font-weight: 800; }
.member-copy { min-width: 0; display: grid; gap: 3px; }
.member-copy strong { overflow: hidden; font-size: 16px; text-overflow: ellipsis; white-space: nowrap; }
.member-copy span { color: var(--chat-muted); font-size: 12px; }
.member-plan { max-width: 125px; overflow: hidden; padding: 6px 9px; border-radius: 999px; background: var(--chat-brand-soft); color: #2f6d59; font-size: 11px; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
.center-tabs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; padding: 4px; border-radius: 13px; background: #f1f5f3; }
.center-tabs button { min-height: 36px; padding: 0 8px; border: 0; border-radius: 10px; background: transparent; color: var(--chat-muted); font-size: 13px; font-weight: 650; white-space: nowrap; }
.center-tabs button[aria-selected="true"] { background: #fff; color: var(--chat-brand-dark); box-shadow: 0 3px 12px rgba(27, 68, 55, 0.08); }
.center-section { display: grid; gap: 15px; }
.entitlement-notice { display: grid; gap: 4px; padding: 11px 13px; border: 1px solid #e7dcb9; border-radius: 12px; background: #fffaf0; color: #735f30; }
.entitlement-notice.expired { border-color: #e6d1cc; background: #fff7f5; color: #76504a; }
.entitlement-notice strong { font-size: 12px; }
.entitlement-notice span { font-size: 11px; line-height: 1.6; }
.plan-card, .review-card, .usage-card, .compact-record, .report-record { border: 1px solid var(--chat-border); border-radius: 14px; background: #fff; }
.plan-card { padding: 14px; background: linear-gradient(145deg, #f2f8f5, #fff); }
.section-heading { display: flex; align-items: center; gap: 9px; color: var(--chat-brand-dark); }
.section-heading > div { display: grid; gap: 2px; }
.section-heading span { color: var(--chat-muted); font-size: 11px; }
.section-heading strong { font-size: 15px; }
.plan-card > p { margin: 10px 0 12px; color: var(--chat-muted); font-size: 13px; line-height: 1.65; }
.plan-meta { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 0; }
.plan-meta div { padding: 9px 10px; border-radius: 10px; background: rgba(255, 255, 255, 0.82); }
.plan-meta dt { color: var(--chat-weak); font-size: 10px; }
.plan-meta dd { margin: 4px 0 0; color: var(--chat-text); font-size: 12px; font-weight: 650; }
.usage-section, .capability-section, .record-group { display: grid; gap: 9px; }
.usage-section h3, .capability-section h3, .record-group h3 { margin: 0; font-size: 14px; }
.usage-card { display: grid; gap: 7px; padding: 12px; }
.usage-card > div:first-child { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; }
.usage-card strong { color: var(--chat-brand-dark); }
.usage-card small, .compact-record time, .report-record time { color: var(--chat-weak); font-size: 11px; }
.usage-track { height: 6px; overflow: hidden; border-radius: 999px; background: #e8efec; }
.usage-track i { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, #4fa486, #1f765d); }
.capability-section ul { display: grid; gap: 1px; margin: 0; padding: 0; overflow: hidden; border: 1px solid var(--chat-border); border-radius: 14px; list-style: none; background: var(--chat-border); }
.capability-section li { display: grid; grid-template-columns: 20px minmax(0, 1fr) auto; align-items: center; gap: 7px; min-height: 42px; padding: 0 12px; background: #fff; color: var(--chat-brand-dark); font-size: 13px; }
.capability-section li small { color: var(--chat-muted); font-size: 10px; }
.capability-section li.unavailable { color: var(--chat-weak); }
.primary-review { padding: 14px; background: var(--chat-brand-soft); }
.primary-review > p { margin: 11px 0 0; font-size: 13px; line-height: 1.75; white-space: pre-wrap; }
.current-focus { margin-top: 12px; padding-top: 11px; border-top: 1px solid rgba(31, 107, 82, 0.12); }
.current-focus span { color: var(--chat-muted); font-size: 11px; }
.current-focus p { margin: 4px 0 0; color: var(--chat-brand-dark); font-size: 13px; line-height: 1.65; }
.compact-record { padding: 11px 12px; }
.compact-record p { margin: 5px 0 0; color: var(--chat-muted); font-size: 12px; line-height: 1.65; white-space: pre-wrap; }
.report-record { overflow: hidden; }
.report-record summary { min-height: 44px; display: grid; grid-template-columns: 20px minmax(0, 1fr) auto; align-items: center; gap: 7px; padding: 0 11px; color: var(--chat-brand-dark); cursor: pointer; }
.report-record summary span { overflow: hidden; font-size: 12px; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
.report-record summary small { color: var(--chat-weak); font-size: 10px; }
.report-record > time { display: block; padding: 0 12px 6px; }
.report-record pre { max-height: 260px; overflow: auto; margin: 0; padding: 11px 12px; border-top: 1px solid var(--chat-border); background: #fbfcfc; color: var(--chat-muted); font: inherit; font-size: 12px; line-height: 1.7; white-space: pre-wrap; }
.center-empty { margin: 0; padding: 22px 14px; border-radius: 14px; background: #f6f8f7; color: var(--chat-muted); font-size: 13px; line-height: 1.7; text-align: center; }
.center-empty.small { padding: 14px; font-size: 12px; }
.personal-center-footer { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.center-logout { min-height: 42px; display: inline-flex; align-items: center; gap: 7px; padding: 0 10px; border: 0; background: transparent; color: #8b5757; font-size: 12px; }
.center-done { width: auto; min-width: 92px; min-height: 42px; padding: 0 18px; border: 0; border-radius: 12px; }
@media (max-width: 360px) {
  .member-plan { max-width: 96px; }
  .center-tabs button { padding: 0 4px; font-size: 12px; }
  .plan-meta { grid-template-columns: 1fr; }
}
</style>
