<script setup lang="ts">
import type { CurrencyCode, LedgerIconKey, LedgerThemeId } from "@cents/domain";
import { BarChart3, Check, ChevronRight, Plus, X } from "@lucide/vue";
import { computed, onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import QuickEntryHost from "../components/QuickEntryHost.vue";
import LedgerIconPicker from "../components/LedgerIconPicker.vue";
import { ApiError } from "../data/api";
import { ledgerIconComponent } from "../data/ledger-icons";
import { ledgerTheme, ledgerThemes } from "../data/ledgers";
import { useEntryStore } from "../stores/entries";
import { useLedgerStore } from "../stores/ledgers";

const router = useRouter();
const route = useRoute();
const entryStore = useEntryStore();
const ledgerStore = useLedgerStore();
const createOpen = ref(false);
const name = ref("");
const themeId = ref<LedgerThemeId>("jade");
const iconKey = ref<LedgerIconKey>("wallet");
const currency = ref<CurrencyCode>("CNY");
const saving = ref(false);
const errorMessage = ref("");

function toMonthValue(date: Date) {
  return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}`;
}

const entryCounts = computed(() => {
  const counts = new Map<string, number>();
  for (const entry of entryStore.entries) {
    for (const ledgerId of entry.ledgerIds) counts.set(ledgerId, (counts.get(ledgerId) ?? 0) + 1);
  }
  return counts;
});

onMounted(async () => {
  await Promise.all([entryStore.loadEntries(), ledgerStore.loadLedgers()]);
});

async function selectLedger(ledgerId: string) {
  await ledgerStore.setCurrentLedger(ledgerId);
  const requestedReturnTo = typeof route.query.returnTo === "string" ? route.query.returnTo : "";
  const returnTo = requestedReturnTo === "/stats" || requestedReturnTo.startsWith("/stats?") ? requestedReturnTo : "/";
  await router.push(returnTo);
}

async function openLedgerStats(ledgerId: string) {
  await ledgerStore.setCurrentLedger(ledgerId);
  await router.push({ name: "stats", query: { range: "month", month: toMonthValue(new Date()), ledgers: ledgerId } });
}

function openCreate() {
  name.value = "";
  themeId.value = ledgerThemes[ledgerStore.ledgers.length % ledgerThemes.length].id;
  iconKey.value = "wallet";
  currency.value = ledgerStore.currentLedger?.defaultCurrency ?? "CNY";
  errorMessage.value = "";
  createOpen.value = true;
}

function closeCreate() {
  if (!saving.value) createOpen.value = false;
}

async function createLedger() {
  const trimmedName = name.value.trim();
  if (!trimmedName || saving.value) return;
  saving.value = true;
  errorMessage.value = "";
  try {
    const theme = ledgerTheme(themeId.value);
    await ledgerStore.createLedger({ name: trimmedName, color: theme.accent, theme: theme.id, icon: iconKey.value, defaultCurrency: currency.value });
    createOpen.value = false;
    await router.push("/");
  } catch (error) {
    errorMessage.value = error instanceof ApiError ? error.message : "创建账本失败，请稍后重试";
  } finally {
    saving.value = false;
  }
}
</script>

<template>
  <main class="app-shell ledgers-shell">
    <header class="section-appbar">
      <strong>账本</strong>
      <span>{{ ledgerStore.ledgers.length }} 个</span>
      <button type="button" aria-label="新增账本" title="新增账本" @click="openCreate"><Plus :size="22" /></button>
    </header>
    <div class="ledgers-scroll">
      <p class="ledgers-caption">当前账本决定流水、统计和快速记账的默认归属。</p>
      <section class="ledger-list" aria-label="全部账本">
        <div v-for="ledger in ledgerStore.ledgers" :key="ledger.id" class="ledger-list-row">
          <button type="button" class="ledger-list-select" @click="selectLedger(ledger.id)">
            <span class="ledger-list-icon" :style="{ background: ledgerTheme(ledger.theme).gradient }"><component :is="ledgerIconComponent(ledger.icon)" :size="22" /></span>
            <span><strong>{{ ledger.name }}</strong><small>{{ entryCounts.get(ledger.id) ?? 0 }} 笔流水 · {{ ledger.isPersonal ? "仅自己可见" : ledger.defaultCurrency }}</small></span>
            <Check v-if="ledgerStore.currentLedgerId === ledger.id" class="current-ledger-check" :size="20" />
            <ChevronRight v-else :size="19" />
          </button>
          <button class="ledger-list-stats" type="button" aria-label="查看统计" title="查看统计" @click="openLedgerStats(ledger.id)"><BarChart3 :size="18" /></button>
        </div>
      </section>
    </div>
    <QuickEntryHost />

    <Transition name="create-sheet">
      <div v-if="createOpen" class="create-ledger-layer" @keydown.esc="closeCreate">
        <button class="create-ledger-scrim" type="button" aria-label="关闭新增账本" @click="closeCreate"></button>
        <form class="create-ledger-sheet" role="dialog" aria-modal="true" aria-labelledby="create-ledger-title" @submit.prevent="createLedger">
          <div class="create-sheet-handle"></div>
          <header>
            <div><strong id="create-ledger-title">新增账本</strong><span>创建后你将成为账本拥有者</span></div>
            <button type="button" aria-label="关闭" title="关闭" @click="closeCreate"><X :size="20" /></button>
          </header>
          <label class="create-ledger-name"><span>账本名称</span><input v-model="name" maxlength="40" placeholder="例如：旅行计划" autocomplete="off" autofocus required /></label>
          <label class="create-ledger-currency"><span>默认币种</span><select v-model="currency"><option value="CNY">人民币 CNY</option><option value="USD">美元 USD</option><option value="EUR">欧元 EUR</option><option value="JPY">日元 JPY</option><option value="THB">泰铢 THB</option><option value="HKD">港币 HKD</option></select></label>
          <fieldset class="create-ledger-colors">
            <legend>账本主题</legend>
            <div><button v-for="theme in ledgerThemes" :key="theme.id" type="button" :class="{ active: themeId === theme.id }" :style="{ background: theme.gradient }" :aria-label="`选择${theme.name}主题`" :title="theme.name" @click="themeId = theme.id"><Check v-if="themeId === theme.id" :size="17" /></button></div>
          </fieldset>
          <fieldset class="create-ledger-icons">
            <legend>账本图标</legend>
            <LedgerIconPicker v-model="iconKey" />
          </fieldset>
          <p v-if="errorMessage" class="create-ledger-error" role="alert">{{ errorMessage }}</p>
          <button class="create-ledger-submit" type="submit" :disabled="saving || !name.trim()"><Plus :size="19" />{{ saving ? "创建中" : "创建账本" }}</button>
        </form>
      </div>
    </Transition>
  </main>
</template>

<style scoped>
.ledgers-shell { background:#f5f8f7; }
.section-appbar { height:70px; display:grid; grid-template-columns:1fr auto 42px; align-items:end; gap:10px; border-bottom:1px solid #dce7e4; padding:14px 12px 8px 18px; background:#fff; }
.section-appbar strong { font-size:20px; }
.section-appbar > span { align-self:center; color:#7b8884; font-size:12px; }
.section-appbar > button { width:42px; height:42px; display:grid; place-items:center; border:0; border-radius:8px; background:transparent; color:#087f72; }
.ledgers-scroll { height:calc(100% - 70px); overflow-y:auto; padding:0 16px 104px; }
.ledgers-caption { margin:16px 0 10px; color:#70807c; font-size:12px; }
.ledger-list { border-top:1px solid #dce7e4; border-bottom:1px solid #dce7e4; background:#fff; }
.ledger-list-row { min-height:72px; display:grid; grid-template-columns:minmax(0,1fr) 42px; border-bottom:1px solid #e6eeec; }
.ledger-list-row:last-child { border-bottom:0; }
.ledger-list-select { width:100%; min-height:72px; display:grid; grid-template-columns:44px minmax(0,1fr) 22px; align-items:center; gap:11px; border:0; padding:8px 8px 8px 12px; background:#fff; color:#26342f; text-align:left; }
.ledger-list-stats { width:36px; height:36px; align-self:center; display:grid; place-items:center; border:0; border-radius:8px; background:#eaf7f3; color:#087f72; }
.ledger-list-icon { width:42px; height:42px; display:grid; place-items:center; border-radius:9px; color:#fff; box-shadow:0 4px 10px rgba(38,59,54,.16); }
.ledger-list button > span:nth-child(2) { min-width:0; display:grid; gap:2px; }
.ledger-list strong { overflow:hidden; font-size:15px; text-overflow:ellipsis; white-space:nowrap; }
.ledger-list small { color:#7b8884; font-size:11px; }
.current-ledger-check { color:#087f72; }
.create-ledger-layer { position:absolute; inset:0; z-index:20; }
.create-ledger-scrim { position:absolute; inset:0; width:100%; height:100%; border:0; background:rgba(18,35,32,.42); backdrop-filter:blur(3px); }
.create-ledger-sheet { position:absolute; right:0; bottom:0; left:0; max-height:calc(100% - 48px); overflow-y:auto; border-radius:14px 14px 0 0; padding:0 16px calc(18px + env(safe-area-inset-bottom)); background:#fff; color:#26342f; box-shadow:0 -16px 36px rgba(22,45,40,.22); }
.create-sheet-handle { width:38px; height:4px; margin:8px auto 3px; border-radius:2px; background:#b9cac5; }
.create-ledger-sheet > header { min-height:58px; display:flex; align-items:center; justify-content:space-between; }
.create-ledger-sheet > header > div { display:grid; gap:1px; }
.create-ledger-sheet > header strong { font-size:17px; }
.create-ledger-sheet > header span,.create-ledger-sheet label > span,.create-ledger-colors legend,.create-ledger-icons legend { color:#7b8884; font-size:11px; }
.create-ledger-sheet > header button { width:38px; height:38px; display:grid; place-items:center; border:0; border-radius:8px; background:#f0f5f3; color:#536762; }
.create-ledger-sheet > label { min-height:64px; display:grid; gap:4px; border-top:1px solid #e2ebe8; padding:10px 2px; }
.create-ledger-sheet input,.create-ledger-sheet select { width:100%; min-width:0; border:0; padding:0; outline:0; background:#fff; color:#26342f; font-size:15px; }
.create-ledger-colors { margin:0; border:0; border-top:1px solid #e2ebe8; padding:12px 2px 15px; }
.create-ledger-colors legend { padding:0; }
.create-ledger-colors > div { display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); gap:7px; width:100%; margin-top:10px; }
.create-ledger-colors button { width:100%; aspect-ratio:1; display:grid; place-items:center; border:3px solid #fff; border-radius:9px; color:#fff; box-shadow:0 0 0 1px #d8e4e1; }
.create-ledger-colors button.active { box-shadow:0 0 0 2px #263b36; }
.create-ledger-icons { margin:0; border:0; border-top:1px solid #e2ebe8; padding:12px 2px 15px; }
.create-ledger-icons legend { padding:0; }
.create-ledger-error { margin:0 0 10px; color:#b83232; font-size:12px; }
.create-ledger-submit { width:100%; height:48px; display:flex; align-items:center; justify-content:center; gap:7px; border:0; border-radius:8px; background:#087f72; color:#fff; font-weight:720; }
.create-ledger-submit:disabled { opacity:.55; }
.create-sheet-enter-active,.create-sheet-leave-active { transition:opacity .2s ease; }
.create-sheet-enter-active .create-ledger-sheet,.create-sheet-leave-active .create-ledger-sheet { transition:transform .22s ease; }
.create-sheet-enter-from,.create-sheet-leave-to { opacity:0; }
.create-sheet-enter-from .create-ledger-sheet,.create-sheet-leave-to .create-ledger-sheet { transform:translateY(100%); }
@media (max-width:360px) { .ledgers-scroll { padding-right:12px; padding-left:12px; } }
</style>
