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

import { api } from "../../shared/api/client";
import { operationsApi, type JobRun } from "../../shared/api/operations";
import { useMarketStore } from "../../shared/stores/market";
import { useUiStore } from "../../shared/stores/ui";

type CredentialStatus = { name: string; configured: boolean; updated_at: string | null };

const labels: Record<string, string> = {
  tushare_token: "Tushare Token",
  ifind_refresh_token: "iFinD Refresh Token",
  ifind_access_token: "iFinD Access Token",
};
const ui = useUiStore();
const market = useMarketStore();
const statuses = ref<CredentialStatus[]>([]);
const values = reactive<Record<string, string>>({});
const loading = ref(true);
const errorMessage = ref("");
const syncing = ref(false);
const syncResult = ref("");
const syncError = ref("");
const jobs = ref<JobRun[]>([]);
const backfill = reactive({ start_date: market.selectedDate, end_date: market.selectedDate });
const backfilling = ref(false);
const operationMessage = ref("");
const event = reactive({
  trade_date: market.selectedDate,
  identifier: "",
  event_type: "limit_up" as "limit_up" | "broken" | "limit_down",
  reason: "",
  first_time: "",
  last_time: "",
  open_times: null as number | null,
});
const eventBusy = ref(false);
const eventHistory = ref<Record<string, unknown>[]>([]);

const jobLabels: Record<string, string> = {
  "market.refresh": "行情刷新",
  "market.backfill": "历史回补",
  "auction.collect": "竞价采集",
  "market.event-supplement": "事件补充",
  "screener.after-close": "盘后选股",
};
const statusLabels = { running: "执行中", completed: "已完成", failed: "失败" };

async function load(): Promise<void> {
  loading.value = true;
  try {
    statuses.value = await api.get<CredentialStatus[]>("/admin/system/credentials");
    jobs.value = await operationsApi.jobs();
  } catch (error) {
    errorMessage.value = error instanceof Error ? error.message : "行情凭据读取失败。";
  } finally {
    loading.value = false;
  }
}

async function loadJobs(): Promise<void> {
  try { jobs.value = await operationsApi.jobs(); }
  catch (error) { ui.showToast(error instanceof Error ? error.message : "任务状态读取失败"); }
}

async function runBackfill(): Promise<void> {
  backfilling.value = true;
  operationMessage.value = "";
  try {
    const result = await operationsApi.backfill(backfill.start_date, backfill.end_date);
    operationMessage.value = `已完成 ${Number(result.completed ?? 0)} 个交易日回补`;
    ui.showToast("历史数据回补已完成");
    await loadJobs();
  } catch (error) {
    ui.showToast(error instanceof Error ? error.message : "历史回补失败");
  } finally { backfilling.value = false; }
}

async function supplementEvents(): Promise<void> {
  eventBusy.value = true;
  try {
    const result = await operationsApi.supplementEvents(event.trade_date);
    operationMessage.value = `事件原因已匹配 ${Number(result.matched ?? 0)} 条`;
    ui.showToast("事件原因补充完成");
    await loadJobs();
  } catch (error) {
    ui.showToast(error instanceof Error ? error.message : "事件补充暂不可用");
  } finally { eventBusy.value = false; }
}

async function reviseEvent(): Promise<void> {
  eventBusy.value = true;
  try {
    await operationsApi.reviseEvent(event.trade_date, event.identifier.trim(), {
      event_type: event.event_type,
      reason: event.reason,
      first_time: event.first_time,
      last_time: event.last_time,
      open_times: event.open_times,
    });
    operationMessage.value = "人工修订已保存，并优先于自动补充内容";
    ui.showToast("事件原因修订已保存");
    await showEventHistory();
  } catch (error) {
    ui.showToast(error instanceof Error ? error.message : "事件修订失败");
  } finally { eventBusy.value = false; }
}

async function showEventHistory(): Promise<void> {
  if (!event.identifier.trim()) return;
  try {
    eventHistory.value = await operationsApi.eventHistory(
      event.trade_date, event.identifier.trim(),
    );
  } catch (error) {
    ui.showToast(error instanceof Error ? error.message : "修订记录读取失败");
  }
}

function duration(value: number | null): string {
  if (value === null) return "";
  return value < 1000 ? `${value} ms` : `${(value / 1000).toFixed(1)} s`;
}

async function save(name: string): Promise<void> {
  const value = values[name]?.trim();
  if (!value) {
    errorMessage.value = "请输入需要保存的凭据。";
    return;
  }
  errorMessage.value = "";
  try {
    await api.put(`/admin/system/credentials/${name}`, { value });
    values[name] = "";
    await load();
    ui.showToast("行情凭据已保存");
  } catch (error) {
    errorMessage.value = error instanceof Error ? error.message : "保存失败，请稍后重试。";
  }
}

async function syncReference(): Promise<void> {
  syncing.value = true;
  syncError.value = "";
  syncResult.value = "";
  try {
    const result = await api.post<{ calendar_days: number; entities: number }>(
      "/market/reference-sync",
    );
    syncResult.value = `已同步 ${result.calendar_days} 个日历日期、${result.entities} 个股票条目`;
    ui.showToast("基础行情资料已同步");
  } catch (error) {
    syncError.value = error instanceof Error ? error.message : "同步失败，请稍后重试。";
  } finally {
    syncing.value = false;
  }
}

onMounted(load);
</script>

<template>
  <div class="system-stack">
    <section class="card">
      <header class="card-header"><h2>平台行情凭据</h2><span class="faint">保存后不再返回明文</span></header>
      <div class="card-body credential-list">
        <p v-if="loading" class="muted">正在读取行情配置</p>
        <div v-for="status in statuses" v-else :key="status.name" class="credential-row">
          <div class="credential-meta">
            <strong>{{ labels[status.name] ?? status.name }}</strong>
            <span :class="status.configured ? 'up' : 'faint'">{{ status.configured ? "已配置" : "未配置" }}</span>
          </div>
          <input v-model="values[status.name]" class="input" type="password" autocomplete="off" placeholder="输入新值后保存" />
          <button class="btn" type="button" @click="save(status.name)">保存</button>
        </div>
        <p v-if="errorMessage" class="field-error" role="alert">{{ errorMessage }}</p>
      </div>
    </section>
    <section class="card">
      <header class="card-header"><h2>基础行情资料</h2><span class="faint">交易日历与股票目录</span></header>
      <div class="card-body disabled-row">
        <p class="muted">保存有效行情凭据后执行；同步结果用于日期判断和全局搜索。</p>
        <span v-if="syncResult" class="up">{{ syncResult }}</span>
        <span v-if="syncError" class="field-error" role="alert">{{ syncError }}</span>
        <button class="btn" type="button" :disabled="syncing" @click="syncReference">
          {{ syncing ? "正在同步" : "同步基础资料" }}
        </button>
      </div>
    </section>
    <section class="card">
      <header class="card-header"><h2>历史数据回补</h2><span class="faint">单次最多15个交易日</span></header>
      <form class="card-body operation-form" @submit.prevent="runBackfill">
        <label class="field"><span class="field-label">开始日期</span><input v-model="backfill.start_date" class="input" type="date" required /></label>
        <label class="field"><span class="field-label">结束日期</span><input v-model="backfill.end_date" class="input" type="date" required /></label>
        <button class="btn" type="submit" :disabled="backfilling">{{ backfilling ? "正在回补" : "开始回补" }}</button>
      </form>
    </section>
    <section class="card">
      <header class="card-header"><h2>事件原因治理</h2><span class="faint">人工修订优先并保留记录</span></header>
      <form class="card-body event-form" @submit.prevent="reviseEvent">
        <label class="field"><span class="field-label">数据日期</span><input v-model="event.trade_date" class="input" type="date" required /></label>
        <label class="field"><span class="field-label">股票代码</span><input v-model="event.identifier" class="input" placeholder="000001.SZ" required /></label>
        <label class="field"><span class="field-label">事件类型</span><select v-model="event.event_type" class="select"><option value="limit_up">涨停</option><option value="broken">炸板</option><option value="limit_down">跌停</option></select></label>
        <label class="field event-reason"><span class="field-label">原因</span><input v-model="event.reason" class="input" maxlength="200" required /></label>
        <label class="field"><span class="field-label">首次时间</span><input v-model="event.first_time" class="input" type="time" /></label>
        <label class="field"><span class="field-label">最后时间</span><input v-model="event.last_time" class="input" type="time" /></label>
        <label class="field"><span class="field-label">开板次数</span><input v-model.number="event.open_times" class="input" type="number" min="0" /></label>
        <div class="table-actions event-actions"><button class="btn btn-primary" type="submit" :disabled="eventBusy">保存修订</button><button class="btn" type="button" :disabled="eventBusy" @click="supplementEvents">自动补充</button><button class="btn" type="button" @click="showEventHistory">查看记录</button></div>
      </form>
      <div v-if="eventHistory.length" class="data-table-wrap event-history"><table class="data-table"><thead><tr><th>时间</th><th>来源</th><th>类型</th><th>原因</th><th>修订人</th></tr></thead><tbody><tr v-for="row in eventHistory" :key="String(row.id)"><td>{{ String(row.created_at).replace('T', ' ').slice(0, 19) }}</td><td>{{ row.source === 'admin' ? '人工修订' : '自动补充' }}</td><td>{{ row.event_type }}</td><td>{{ row.reason }}</td><td>{{ row.created_by_name ?? '' }}</td></tr></tbody></table></div>
    </section>
    <section class="card">
      <header class="card-header"><h2>后台任务状态</h2><button class="btn btn-small" type="button" @click="loadJobs">刷新状态</button></header>
      <p v-if="operationMessage" class="notice">{{ operationMessage }}</p>
      <div v-if="jobs.length" class="data-table-wrap operation-jobs"><table class="data-table"><thead><tr><th>任务</th><th>数据日期</th><th>状态</th><th>开始时间</th><th class="numeric">耗时</th><th class="numeric">覆盖率（%）</th><th>说明</th></tr></thead><tbody><tr v-for="job in jobs" :key="job.id"><td>{{ jobLabels[job.kind] ?? job.kind }}</td><td>{{ job.requested_date }}</td><td><span class="tag" :class="{ warning: job.status === 'failed' }">{{ statusLabels[job.status] }}</span></td><td>{{ job.started_at.replace('T', ' ').slice(0, 19) }}</td><td class="numeric">{{ duration(job.duration_ms) }}</td><td class="numeric">{{ job.coverage === null ? '' : (job.coverage * 100).toFixed(1) }}</td><td>{{ job.error_message }}</td></tr></tbody></table></div>
      <p v-else class="card-body muted">暂无后台任务记录</p>
    </section>
  </div>
</template>
