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

import { marketApi, type MarketEntity, type MarketInsightData, type ThemeDetailData } from "../../../shared/api/market";
import DataTable from "../../../shared/components/DataTable.vue";
import EmptyState from "../../../shared/components/EmptyState.vue";
import MarketPreviewPanel from "../../../shared/market/MarketPreviewPanel.vue";
import { formatAmount, formatNumber, sortRows, type SortDirection } from "../../../shared/market/table";

const props = defineProps<{ data: MarketInsightData }>();
const query = ref("");
const selectedCode = ref("");
const detail = ref<ThemeDetailData | null>(null);
const loading = ref(false);
const error = ref("");
const preview = ref<MarketEntity | null>(null);
const sortKey = ref("change");
const sortDirection = ref<SortDirection>("desc");
let requestSequence = 0;
const themes = computed(() => {
  const normalized = query.value.trim().toLocaleLowerCase();
  return (props.data.items ?? []).filter((item) => !normalized || [item.code, item.name]
    .some((value) => String(value ?? "").toLocaleLowerCase().includes(normalized)));
});
const members = computed(() => sortRows(detail.value?.members ?? [], sortKey.value, sortDirection.value));
const columns = [
  { key: "code", label: "代码", code: true, sortable: true },
  { key: "name", label: "股票", sortable: true },
  { key: "change", label: "涨跌幅（%）", numeric: true, sortable: true, format: number },
  { key: "close", label: "收盘价（元）", numeric: true, sortable: true, format: number },
  { key: "amount", label: "成交额", numeric: true, sortable: true, format: amount },
  { key: "quoted", label: "行情状态", sortable: true, format: quoteState },
];

watch(() => props.data.trade_date, () => {
  const first = props.data.items?.[0];
  if (first) void selectTheme(first);
}, { immediate: true });

async function selectTheme(theme: Record<string, unknown>): Promise<void> {
  const code = String(theme.code ?? "");
  if (!code) return;
  selectedCode.value = code;
  const sequence = ++requestSequence;
  loading.value = true;
  error.value = "";
  try {
    const result = await marketApi.themeDetail(code, props.data.trade_date ?? props.data.requested_date);
    if (sequence === requestSequence) detail.value = result;
  } catch (reason) {
    if (sequence === requestSequence) {
      detail.value = null;
      error.value = reason instanceof Error ? reason.message : "题材成分股读取失败";
    }
  } finally {
    if (sequence === requestSequence) loading.value = false;
  }
}
function showPreview(theme: Record<string, unknown>): void {
  const identifier = String(theme.code ?? "");
  preview.value = identifier ? {
    entity_type: "theme",
    identifier,
    code: identifier.split(".")[0] ?? identifier,
    name: String(theme.name ?? ""),
    sector: null,
  } : null;
}
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); }
function amount(value: unknown): string { return formatAmount(value); }
function quoteState(value: unknown): string { return value ? "正常交易" : "当日无行情"; }
</script>

<template>
  <header class="page-header market-page-header">
    <div><h1>题材库</h1><p class="page-subtitle">题材排行与成分行情 · 数据日期 {{ data.trade_date }}</p></div>
    <span v-if="data.message" class="tag warning">{{ data.message }}</span>
  </header>
  <section class="themes-layout">
    <article class="card theme-directory">
      <header class="card-header"><h2>题材排行</h2><span class="faint">{{ data.summary.theme_count ?? 0 }}个题材</span></header>
      <label class="search-control theme-search"><span>搜索</span><input v-model="query" type="search" placeholder="题材名称或代码"></label>
      <div class="theme-rank-list">
        <button v-for="(theme, index) in themes" :key="String(theme.code)" type="button" :class="{ active: selectedCode === theme.code }" @click="selectTheme(theme)" @mouseenter="showPreview(theme)" @mouseleave="preview = null">
          <b>{{ index + 1 }}</b><span><strong>{{ theme.name }}</strong><small>{{ theme.code }}</small></span><em :class="{ up: Number(theme.change) > 0, down: Number(theme.change) < 0 }">{{ theme.change === null ? '' : `${number(theme.change)}%` }}</em>
        </button>
      </div>
      <div v-if="preview" class="theme-preview-popover"><MarketPreviewPanel :entity="preview" /></div>
    </article>
    <article class="card theme-detail-card">
      <header class="card-header"><h2>{{ detail?.theme.name || "题材基础行情" }}</h2><span class="faint">{{ detail?.theme.code || "选择左侧题材" }}</span></header>
      <div v-if="detail" class="theme-summary-strip">
        <div><span>成分股</span><strong>{{ detail.summary.member_count ?? 0 }}</strong></div>
        <div><span>有行情</span><strong>{{ detail.summary.quoted_count ?? 0 }}</strong></div>
        <div><span>上涨</span><strong class="up">{{ detail.summary.up_count ?? 0 }}</strong></div>
        <div><span>下跌</span><strong class="down">{{ detail.summary.down_count ?? 0 }}</strong></div>
        <div><span>换手率</span><strong>{{ number(detail.summary.turnover_rate) }}%</strong></div>
      </div>
      <div v-if="loading" class="workspace-state">正在核验题材成分行情</div>
      <EmptyState v-else-if="error" title="题材成分暂不可用" :description="error" />
      <DataTable v-else-if="members.length" :columns="columns" :rows="members" :sort-key="sortKey" :sort-direction="sortDirection" @sort="sort" />
      <EmptyState v-else title="暂无题材成分数据" :description="detail?.message || '选择左侧题材后显示成分股。'" />
    </article>
  </section>
</template>
