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

import type { MarketWorkspaceData } from "../../../shared/api/market";
import DataTable from "../../../shared/components/DataTable.vue";
import EmptyState from "../../../shared/components/EmptyState.vue";

type PoolKind = "pool" | "broken" | "limit-down" | "yesterday";
type FilterOption = readonly [value: string, label: string];
type Column = {
  key: string;
  label: string;
  numeric?: boolean;
  wide?: boolean;
  code?: boolean;
  sortable?: boolean;
  format?: (value: unknown, row: Record<string, unknown>) => string;
};

const props = defineProps<{ kind: string; data: MarketWorkspaceData }>();
const search = ref("");
const filter = ref("all");
const sortKey = ref("");
const sortDirection = ref<"asc" | "desc">("desc");

const definitions: Record<PoolKind, { title: string; description: string; columns: Column[] }> = {
  pool: {
    title: "涨停池",
    description: "当日封板股票与连板结构",
    columns: [
      { key: "code", label: "代码", code: true, sortable: true },
      { key: "name", label: "股票", sortable: true },
      { key: "streak", label: "连板", numeric: true, sortable: true },
      { key: "change", label: "涨幅（%）", numeric: true, sortable: true, format: percent },
      { key: "price", label: "价格（元）", numeric: true, sortable: true, format: decimal },
      { key: "sector", label: "板块", sortable: true },
      { key: "first_time", label: "首封", sortable: true },
      { key: "last_time", label: "最后封板", sortable: true },
      { key: "open_times", label: "开板次数", numeric: true, sortable: true },
      { key: "turnover_rate", label: "换手率（%）", numeric: true, sortable: true, format: percent },
      { key: "amount", label: "成交额（亿）", numeric: true, sortable: true, format: amount },
      { key: "seal_amount", label: "封单额（亿）", numeric: true, sortable: true, format: amount },
      { key: "reason", label: "涨停原因", wide: true },
    ],
  },
  broken: {
    title: "炸板池",
    description: "触板未封股票与开板情况",
    columns: [
      { key: "code", label: "代码", code: true, sortable: true },
      { key: "name", label: "股票", sortable: true },
      { key: "change", label: "现价涨幅（%）", numeric: true, sortable: true, format: percent },
      { key: "distance_to_limit", label: "距涨停（%）", numeric: true, sortable: true, format: percent },
      { key: "price", label: "价格（元）", numeric: true, sortable: true, format: decimal },
      { key: "sector", label: "板块", sortable: true },
      { key: "first_time", label: "首次触板", sortable: true },
      { key: "open_times", label: "开板次数", numeric: true, sortable: true },
      { key: "turnover_rate", label: "换手率（%）", numeric: true, sortable: true, format: percent },
      { key: "amount", label: "成交额（亿）", numeric: true, sortable: true, format: amount },
      { key: "reason", label: "炸板原因", wide: true },
    ],
  },
  "limit-down": {
    title: "跌停池",
    description: "跌停风险与行业聚集",
    columns: [
      { key: "code", label: "代码", code: true, sortable: true },
      { key: "name", label: "股票", sortable: true },
      { key: "change", label: "跌幅（%）", numeric: true, sortable: true, format: percent },
      { key: "price", label: "价格（元）", numeric: true, sortable: true, format: decimal },
      { key: "sector", label: "板块", sortable: true },
      { key: "turnover_rate", label: "换手率（%）", numeric: true, sortable: true, format: percent },
      { key: "amount", label: "成交额（亿）", numeric: true, sortable: true, format: amount },
      { key: "streak", label: "连续跌停", numeric: true, sortable: true },
      { key: "reason", label: "风险线索", wide: true },
    ],
  },
  yesterday: {
    title: "昨日涨停",
    description: "昨日涨停股票的次日反馈",
    columns: [
      { key: "code", label: "代码", code: true, sortable: true },
      { key: "name", label: "股票", sortable: true },
      { key: "prior_streak", label: "昨日高度", numeric: true, sortable: true },
      { key: "current_change", label: "今日涨幅（%）", numeric: true, sortable: true, format: percent },
      { key: "outcome", label: "今日结果", sortable: true },
      { key: "current_streak", label: "当前高度", numeric: true, sortable: true },
      { key: "sector", label: "板块", sortable: true },
      { key: "reason", label: "涨停逻辑", wide: true },
    ],
  },
};

const definition = computed(() => definitions[props.kind as PoolKind] ?? definitions.pool);
const sourceRows = computed(() => props.data.items ?? []);
const filters = computed<FilterOption[]>(() => props.kind === "pool"
  ? [["all", "全部"], ["first", "首板"], ["second", "2板"], ["three", "3板+"]]
  : props.kind === "yesterday"
    ? [["all", "全部"], ["advanced", "晋级"], ["red", "红盘"], ["broken", "断板"], ["failed", "炸板+跌停"]]
    : []);
const rows = computed(() => {
  const keyword = search.value.trim().toLocaleLowerCase();
  const filtered = sourceRows.value.filter((row) => {
    const matchesSearch = !keyword || [row.code, row.name, row.sector]
      .some((value) => String(value ?? "").toLocaleLowerCase().includes(keyword));
    if (!matchesSearch) return false;
    if (props.kind === "pool") {
      const streak = Number(row.streak ?? 0);
      return filter.value === "all" || (filter.value === "first" && streak === 1)
        || (filter.value === "second" && streak === 2) || (filter.value === "three" && streak >= 3);
    }
    if (props.kind === "yesterday") {
      const outcome = String(row.outcome ?? "");
      return filter.value === "all" || (filter.value === "advanced" && outcome === "晋级")
        || (filter.value === "red" && outcome === "红盘") || (filter.value === "broken" && outcome === "断板")
        || (filter.value === "failed" && ["炸板", "跌停"].includes(outcome));
    }
    return true;
  });
  if (!sortKey.value) return filtered;
  const direction = sortDirection.value === "asc" ? 1 : -1;
  return [...filtered].sort((left, right) => compare(left[sortKey.value], right[sortKey.value]) * direction);
});
const sectorSummary = computed(() => {
  const counts = new Map<string, number>();
  for (const row of sourceRows.value) {
    const sector = String(row.sector ?? "").trim();
    if (sector) counts.set(sector, (counts.get(sector) ?? 0) + 1);
  }
  return [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 6);
});
const maxHeight = computed(() => Math.max(0, ...sourceRows.value.map((row) => Number(row.streak ?? 0))));
const positiveRate = computed(() => sourceRows.value.length
  ? sourceRows.value.filter((row) => Number(row.current_change ?? 0) > 0).length / sourceRows.value.length * 100
  : 0);

watch(() => props.kind, () => { filter.value = "all"; search.value = ""; sortKey.value = ""; });

function sort(key: string): void {
  if (sortKey.value === key) sortDirection.value = sortDirection.value === "asc" ? "desc" : "asc";
  else { sortKey.value = key; sortDirection.value = "desc"; }
}

function exportCsv(): void {
  const columns = definition.value.columns;
  const values = [columns.map((column) => column.label), ...rows.value.map((row) => columns.map((column) => {
    const value = column.format ? column.format(row[column.key], row) : String(row[column.key] ?? "");
    return `"${value.replaceAll('"', '""')}"`;
  }))];
  const blob = new Blob(["\ufeff", values.map((line) => line.join(",")).join("\r\n")], { type: "text/csv;charset=utf-8" });
  const link = document.createElement("a");
  link.href = URL.createObjectURL(blob);
  link.download = `${definition.value.title}-${props.data.trade_date}.csv`;
  link.click();
  URL.revokeObjectURL(link.href);
}

function compare(left: unknown, right: unknown): number {
  const a = Number(left); const b = Number(right);
  if (Number.isFinite(a) && Number.isFinite(b)) return a - b;
  return String(left ?? "").localeCompare(String(right ?? ""), "zh-CN");
}
function numeric(value: unknown, digits: number): string {
  if (value === null || value === undefined || value === "") return "";
  const number = Number(value);
  return Number.isFinite(number) ? number.toFixed(digits) : "";
}
function percent(value: unknown): string { return numeric(value, 2); }
function decimal(value: unknown): string { return numeric(value, 2); }
function amount(value: unknown): string {
  if (value === null || value === undefined || value === "") return "";
  const number = Number(value);
  return Number.isFinite(number) ? (number / 100_000_000).toFixed(2) : "";
}
</script>

<template>
  <header class="page-header market-page-header">
    <div><h1>{{ definition.title }}</h1><p class="page-subtitle">{{ definition.description }} · 数据日期 {{ data.trade_date }}</p></div>
    <span v-if="data.message" class="tag warning">{{ data.message }}</span>
  </header>
  <section v-if="kind === 'yesterday'" class="pool-summary-grid">
    <article class="card summary-metric"><span>昨日涨停</span><strong>{{ sourceRows.length }}</strong></article>
    <article class="card summary-metric"><span>晋级</span><strong>{{ sourceRows.filter((row) => row.outcome === '晋级').length }}</strong></article>
    <article class="card summary-metric"><span>红盘兑现率</span><strong>{{ positiveRate.toFixed(1) }}%</strong></article>
  </section>
  <section class="pool-layout" :class="{ 'pool-layout-single': !['pool', 'limit-down'].includes(kind) }">
    <article class="card pool-table-card">
      <header class="pool-toolbar">
        <div v-if="filters.length" class="seg-control pool-filters">
          <button v-for="item in filters" :key="item[0]" type="button" :class="{ active: filter === item[0] }" @click="filter = item[0]">{{ item[1] }}</button>
        </div>
        <input v-model="search" class="input pool-search" type="search" placeholder="搜索代码、股票或板块" aria-label="搜索股池" />
        <button class="btn btn-small" type="button" @click="exportCsv">导出 CSV</button>
      </header>
      <DataTable v-if="rows.length" :columns="definition.columns" :rows="rows" :sort-key="sortKey" :sort-direction="sortDirection" @sort="sort" />
      <EmptyState v-else title="暂无符合条件个股" description="当前真实快照中没有满足筛选条件的记录。" />
    </article>
    <aside v-if="kind === 'pool'" class="pool-aside">
      <article class="card"><header class="card-header"><h2>连板高度</h2></header><div class="pool-stat-body"><strong>{{ maxHeight }}板</strong><span>当前市场最高连板</span></div></article>
      <article class="card"><header class="card-header"><h2>热点板块</h2></header><ol class="sector-list"><li v-for="item in sectorSummary" :key="item[0]"><span>{{ item[0] }}</span><strong>{{ item[1] }}家</strong></li></ol></article>
    </aside>
    <aside v-else-if="kind === 'limit-down'" class="pool-aside">
      <article class="card"><header class="card-header"><h2>风险行业聚集</h2></header><ol class="sector-list"><li v-for="item in sectorSummary" :key="item[0]"><span>{{ item[0] }}</span><strong>{{ item[1] }}家</strong></li></ol><p class="risk-note">仅表示当日跌停数量聚集，不构成个股确定性结论。</p></article>
    </aside>
  </section>
</template>
