<script setup lang="ts">
import { computed, reactive, ref, watch } from "vue";

import { marketApi, type MarketInsightData } from "../../../shared/api/market";
import DataTable from "../../../shared/components/DataTable.vue";
import EmptyState from "../../../shared/components/EmptyState.vue";
import { formatNumber, sortRows, type SortDirection } from "../../../shared/market/table";
import { useSessionStore } from "../../../shared/stores/session";
import { useUiStore } from "../../../shared/stores/ui";

const props = defineProps<{ data: MarketInsightData }>();
const emit = defineEmits<{ refresh: [] }>();
const session = useSessionStore();
const ui = useUiStore();
const view = ref<"daily" | "profiles">("daily");
const filter = ref<"all" | "buy" | "sell" | "pending">("all");
const query = ref("");
const selectedTrader = ref("");
const selectedProfile = ref("");
const sortKey = ref("net_million");
const sortDirection = ref<SortDirection>("desc");
const aliases = reactive<Record<string, string>>({});
const savingSeat = ref("");
const traders = computed(() => props.data.traders ?? []);
const profiles = computed(() => props.data.profiles ?? []);
const profile = computed(() => profiles.value.find((item) => item.name === selectedProfile.value) ?? profiles.value[0]);
const operations = computed(() => {
  const normalized = query.value.trim().toLocaleLowerCase();
  const rows = (props.data.operations ?? []).filter((row) => {
    if (selectedTrader.value && row.trader_name !== selectedTrader.value) return false;
    if (filter.value === "buy" && Number(row.net_million ?? 0) <= 0) return false;
    if (filter.value === "sell" && Number(row.net_million ?? 0) >= 0) return false;
    if (filter.value === "pending" && row.recognized) return false;
    if (!normalized) return true;
    return [row.code, row.name, row.seat_name, row.trader_name, row.reason]
      .some((value) => String(value ?? "").toLocaleLowerCase().includes(normalized));
  });
  return sortRows(rows, sortKey.value, sortDirection.value);
});
const columns = [
  { key: "code", label: "代码", code: true, sortable: true },
  { key: "name", label: "股票", sortable: true },
  { key: "direction", label: "方向", sortable: true },
  { key: "buy_million", label: "买入（百万）", numeric: true, sortable: true, format: number },
  { key: "sell_million", label: "卖出（百万）", numeric: true, sortable: true, format: number },
  { key: "net_million", label: "净额（百万）", numeric: true, sortable: true, format: number },
  { key: "trader_name", label: "游资", sortable: true },
  { key: "seat_name", label: "营业部", wide: true, sortable: true },
  { key: "reason", label: "上榜原因", wide: true },
];

watch(profiles, (items) => {
  if (!selectedProfile.value && items[0]) selectedProfile.value = String(items[0].name ?? "");
}, { immediate: true });

function sort(key: string): void {
  if (sortKey.value === key) sortDirection.value = sortDirection.value === "asc" ? "desc" : "asc";
  else { sortKey.value = key; sortDirection.value = "desc"; }
}
function number(value: unknown): string { return formatNumber(value, 2); }
async function saveAlias(seat: string): Promise<void> {
  const alias = aliases[seat]?.trim();
  if (!alias) return;
  savingSeat.value = seat;
  try {
    await marketApi.saveSeatAlias(seat, alias);
    ui.showToast("席位归类已保存");
    emit("refresh");
  } catch (reason) {
    ui.showToast(reason instanceof Error ? reason.message : "席位归类保存失败");
  } finally {
    savingSeat.value = "";
  }
}
</script>

<template>
  <header class="page-header market-page-header">
    <div><h1>龙虎榜</h1><p class="page-subtitle">上榜明细与活跃席位 · 数据日期 {{ data.trade_date }}</p></div>
    <div class="page-actions"><div class="seg-control"><button type="button" :class="{ active: view === 'daily' }" @click="view = 'daily'">每日明细</button><button type="button" :class="{ active: view === 'profiles' }" @click="view = 'profiles'">游资档案</button></div></div>
  </header>
  <template v-if="view === 'daily'">
    <section class="dragon-summary-grid">
      <article class="card"><span>上榜股票</span><strong>{{ data.summary.official_stock_count ?? 0 }}</strong></article>
      <article class="card"><span>活跃游资</span><strong>{{ data.summary.trader_count ?? 0 }}</strong></article>
      <article class="card"><span>操作明细</span><strong>{{ data.summary.operation_count ?? 0 }}</strong></article>
      <article class="card"><span>待归类席位</span><strong>{{ data.summary.unclassified_count ?? 0 }}</strong></article>
      <article class="card"><span>席位净额</span><strong>{{ number(data.summary.net_million) }} 百万</strong></article>
    </section>
    <div v-if="data.message" class="notice" :class="data.status === 'unavailable' ? 'notice-warning' : ''">{{ data.message }}<span v-if="data.previous_date"> · 可切换至 {{ data.previous_date }} 查看</span></div>
    <section v-if="data.status !== 'empty' && data.status !== 'detail_missing' && data.status !== 'unavailable'" class="dragon-daily-layout">
      <aside class="card dragon-traders">
        <header class="card-header"><h2>活跃游资</h2><button v-if="selectedTrader" class="btn btn-small" type="button" @click="selectedTrader = ''">显示全部</button></header>
        <div class="dragon-trader-list"><button v-for="trader in traders" :key="String(trader.name)" type="button" :class="{ active: selectedTrader === trader.name }" @click="selectedTrader = String(trader.name)"><span><strong>{{ trader.name }}</strong><small>{{ trader.description || '暂无简介' }}</small></span><b :class="Number(trader.net_million) >= 0 ? 'up' : 'down'">{{ number(trader.net_million) }}</b></button><p v-if="!traders.length" class="faint">当前没有已识别游资</p></div>
        <section v-if="data.unclassified_seats?.length" class="dragon-pending"><header><strong>待归类营业部</strong><span>{{ data.unclassified_seats.length }}个</span></header><div v-for="seat in data.unclassified_seats" :key="String(seat.seat_name)"><p><span>{{ seat.seat_name }}</span><b>{{ number(seat.net_million) }}</b></p><form v-if="session.isAdmin" @submit.prevent="saveAlias(String(seat.seat_name))"><input v-model="aliases[String(seat.seat_name)]" type="text" placeholder="归类为游资名称"><button class="btn btn-small" type="submit" :disabled="savingSeat === seat.seat_name">保存</button></form></div></section>
      </aside>
      <article class="card dragon-operations">
        <header class="card-header"><h2>当日操作明细</h2><span class="faint">{{ operations.length }}条</span></header>
        <div class="dragon-toolbar"><div class="seg-control"><button type="button" :class="{ active: filter === 'all' }" @click="filter = 'all'">全部</button><button type="button" :class="{ active: filter === 'buy' }" @click="filter = 'buy'">净买入</button><button type="button" :class="{ active: filter === 'sell' }" @click="filter = 'sell'">净卖出</button><button type="button" :class="{ active: filter === 'pending' }" @click="filter = 'pending'">待归类</button></div><label class="search-control"><span>搜索</span><input v-model="query" type="search" placeholder="代码、股票、游资或营业部"></label></div>
        <div class="dragon-table-scroll"><DataTable v-if="operations.length" :columns="columns" :rows="operations" :sort-key="sortKey" :sort-direction="sortDirection" @sort="sort" /><EmptyState v-else title="暂无符合条件的操作明细" description="调整筛选条件或选择其他活跃游资。" /></div>
      </article>
    </section>
    <EmptyState v-else class="card" :title="data.status === 'empty' ? '当日没有股票上榜' : data.status === 'detail_missing' ? '席位明细尚未返回' : '龙虎榜数据暂不可用'" :description="data.message" />
  </template>
  <section v-else class="card dragon-profiles">
    <aside><header class="card-header"><h2>游资名录</h2><span class="faint">{{ profiles.length }}位</span></header><div><button v-for="item in profiles" :key="String(item.name)" type="button" :class="{ active: profile?.name === item.name }" @click="selectedProfile = String(item.name)"><strong>{{ item.name }}</strong><small>{{ item.organization_count }}个关联营业部</small></button></div></aside>
    <article v-if="profile"><header><div><h2>{{ profile.name }}</h2><p>{{ profile.description || '暂无公开简介' }}</p></div><span class="tag">{{ profile.organization_count }}个营业部</span></header><section><h3>关联营业部</h3><ul><li v-for="organization in profile.organizations as string[]" :key="organization">{{ organization }}</li></ul></section><p class="notice">档案统计以当前可用名录和已归类席位为准，覆盖范围会随归档累积。</p></article>
    <EmptyState v-else title="游资名录暂不可用" description="当前没有可核验的游资档案。" />
  </section>
</template>
