<script lang="ts" setup>
/**
 * 金方导入预览弹窗
 * - 解析后的行在这里表格预览
 * - 顶部全局「金方来源」选择器：下拉选已有 + 输入新增，所有行共用同一 source_id
 * - 打开后批量排查药品存在性（中药饮片 type=1 + 别名表），表格加「不存在的药品」列红字标记
 * - 确认导入时 emit { rows, sourceId }，sourceId 为空提示选择来源
 */
import { computed, ref } from 'vue';

import { useVbenModal } from '@vben/common-ui';

import {
  Button,
  Input,
  Select,
  Table,
  Tag,
  Tooltip,
  message,
} from 'ant-design-vue';

import {
  checkGoldenFormulaDrugs,
  createGoldenFormulaSource,
  getGoldenFormulaSourceOption,
} from '../api';

const emit = defineEmits<{
  (e: 'confirm', payload: { rows: any[]; sourceId: number }): void;
}>();

// 预览的原始行（Excel 解析后）
const rows = ref<any[]>([]);
// 金方来源下拉选项
const sourceOptions = ref<{ label: string; value: number }[]>([]);
// 选中的金方来源 id
const sourceId = ref<number>(0);
// 新增来源输入框文案
const newSourceName = ref('');
// 来源下拉 loading
const sourceLoading = ref(false);
// 新增来源提交中
const creatingSource = ref(false);
// 药品排查：不存在的药名集合
const missingSet = ref<Set<string>>(new Set());
// 排查中
const checking = ref(false);

const [Modal, modalApi] = useVbenModal({
  fullscreenButton: false,
  draggable: true,
  class: 'w-[90%]',
  onCancel() {
    modalApi.close();
  },
  onConfirm: async () => {
    if (sourceId.value <= 0) {
      message.warning('请选择金方来源');
      return;
    }
    if (!rows.value.length) {
      message.warning('没有可导入的数据');
      return;
    }
    emit('confirm', { rows: rows.value, sourceId: sourceId.value });
    modalApi.close();
  },
  async onOpenChange(isOpen: boolean) {
    if (!isOpen) {
      // 关闭时重置状态
      rows.value = [];
      sourceId.value = 0;
      newSourceName.value = '';
      missingSet.value = new Set();
      return;
    }
    const data = modalApi.getData<{ rows?: any[] }>() || {};
    rows.value = Array.isArray(data.rows) ? data.rows : [];
    await loadSourceOptions();
    // 打开后批量排查药品存在性
    await runDrugCheck();
  },
});

/** 加载金方来源下拉 */
async function loadSourceOptions() {
  sourceLoading.value = true;
  try {
    const list = await getGoldenFormulaSourceOption();
    sourceOptions.value = (Array.isArray(list) ? list : []).map((item: any) => ({
      label: String(item.name || ''),
      value: Number(item.id || 0),
    }));
  } catch (e: any) {
    sourceOptions.value = [];
    message.error(e?.message || '加载金方来源失败');
  } finally {
    sourceLoading.value = false;
  }
}

/** 新增来源：成功后刷新下拉并选中 */
async function handleCreateSource() {
  const name = newSourceName.value.trim();
  if (!name) {
    message.warning('请输入来源名称');
    return;
  }
  // 已存在同名则直接选中
  const exist = sourceOptions.value.find(
    (o) => o.label === name || o.label.includes(name),
  );
  if (exist) {
    sourceId.value = exist.value;
    newSourceName.value = '';
    message.success('已存在该来源，已自动选中');
    return;
  }
  creatingSource.value = true;
  try {
    const res = await createGoldenFormulaSource({ name });
    const newId = Number(res?.id || 0);
    if (newId > 0) {
      await loadSourceOptions();
      sourceId.value = newId;
      newSourceName.value = '';
      message.success('来源新增成功');
    }
  } catch (e: any) {
    message.error(e?.message || '新增来源失败');
  } finally {
    creatingSource.value = false;
  }
}

/**
 * 从所有行的 drugs_json 收集药名，去重后批量排查存在性
 */
async function runDrugCheck() {
  if (!rows.value.length) {
    missingSet.value = new Set();
    return;
  }
  const nameSet = new Set<string>();
  for (const row of rows.value) {
    const raw = row?.drugs_json;
    if (!raw) continue;
    try {
      const arr = typeof raw === 'string' ? JSON.parse(raw) : raw;
      if (Array.isArray(arr)) {
        for (const item of arr) {
          const n = String(item?.name || item?.drug_name || '').trim();
          if (n) nameSet.add(n);
        }
      }
    } catch {
      // JSON 非法则跳过该行
    }
  }
  const names = Array.from(nameSet);
  if (!names.length) {
    missingSet.value = new Set();
    return;
  }
  checking.value = true;
  try {
    const res = await checkGoldenFormulaDrugs({ drug_names: names });
    const missing = Array.isArray(res?.missing) ? res.missing : [];
    missingSet.value = new Set(missing);
  } catch (e: any) {
    // 排查失败不阻塞预览
    missingSet.value = new Set();
  } finally {
    checking.value = false;
  }
}

/** 计算单行的「不存在的药品」列表（该行药名 ∩ 缺失集合） */
function rowMissingDrugs(row: any): string[] {
  const raw = row?.drugs_json;
  if (!raw) return [];
  let arr: any[] = [];
  try {
    const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
    if (Array.isArray(parsed)) arr = parsed;
  } catch {
    return [];
  }
  const result: string[] = [];
  for (const item of arr) {
    const n = String(item?.name || item?.drug_name || '').trim();
    if (n && missingSet.value.has(n)) result.push(n);
  }
  return result;
}

/** 汇总：不存在的药品总数（用于顶部提示） */
const missingSummary = computed(() => Array.from(missingSet.value));

/**
 * 判定单行是否异常处方
 * - drugs_json 解析后是对象且含 error（如 {error:无数据}）
 * - 或规范化后药味数为 0（空数组 / 无法解析出有效药名）
 */
function isAbnormalRow(row: any): boolean {
  const raw = row?.drugs_json;
  if (raw === null || raw === undefined || raw === '') return true;
  let parsed: any;
  try {
    parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
  } catch {
    return true;
  }
  if (!parsed || typeof parsed !== 'object') return true;
  // 关联对象含 error：典型 {"error":"无数据"}
  if (!Array.isArray(parsed) && Object.prototype.hasOwnProperty.call(parsed, 'error')) {
    return true;
  }
  const list = Array.isArray(parsed)
    ? parsed
    : Array.isArray(parsed?.drugs)
      ? parsed.drugs
      : Array.isArray(parsed?.items)
        ? parsed.items
        : [];
  // 药味数为 0
  const count = list.filter(
    (item: any) => String(item?.name || item?.drug_name || '').trim() !== '',
  ).length;
  return count === 0;
}

/** 异常处方数量（顶部提示用） */
const abnormalCount = computed(
  () => rows.value.filter((r) => isAbnormalRow(r)).length,
);
</script>
<template>
  <Modal title="金方导入预览">
    <div class="flex flex-col gap-3">
      <!-- 顶部：金方来源全局选择器 + 新增 -->
      <div class="flex flex-wrap items-center gap-2">
        <span class="text-sm font-medium">金方来源：</span>
        <Select
          v-model:value="sourceId"
          :options="sourceOptions"
          :loading="sourceLoading"
          show-search
          option-filter-prop="label"
          placeholder="选择已有金方来源"
          style="min-width: 220px"
        />
        <span class="text-xs text-muted-foreground">或新增：</span>
        <Input
          v-model:value="newSourceName"
          placeholder="输入新来源名称"
          style="width: 200px"
          @press-enter="handleCreateSource"
        />
        <Button
          type="primary"
          :loading="creatingSource"
          size="small"
          @click="handleCreateSource"
        >
          新增来源
        </Button>
      </div>

      <!-- 异常处方提示（仅警告，不拦截） -->
      <div
        v-if="abnormalCount > 0"
        class="rounded-lg border border-red-500/35 bg-red-500/10 px-3 py-2 text-xs"
      >
        <span class="font-medium">⚠ 异常处方：</span>
        共
        <Tag color="error" class="!mx-1">{{ abnormalCount }}</Tag>
        条（药品JSON含 error 或药味数为 0），仍可导入，入库后标记为异常
      </div>

      <!-- 药品存在性排查提示（仅警告，不拦截） -->
      <div
        v-if="missingSummary.length"
        class="rounded-lg border border-orange-500/35 bg-orange-500/10 px-3 py-2 text-xs"
      >
        <span class="font-medium">⚠ 药品排查：</span>
        共发现
        <Tag color="orange" class="!mx-1">{{ missingSummary.length }}</Tag>
        个不存在的药品（仅提示，不拦截导入）：
        <span class="text-orange-700">{{ missingSummary.join('、') }}</span>
        <span v-if="checking" class="ml-2 text-muted-foreground">排查中…</span>
      </div>

      <!-- 预览表格 -->
      <Table
        :columns="[
          { title: '序号', width: 60, customRender: ({ index }) => index + 1 },
          { title: '药方名字', dataIndex: 'name', width: 140 },
          { title: '条文编号', dataIndex: 'clause_number', width: 110 },
          { title: '状态', key: 'abnormal', width: 90 },
          {
            title: '药品JSON',
            dataIndex: 'drugs_json',
            ellipsis: true,
            customRender: ({ text }) => String(text || ''),
          },
          { title: '药材速览', dataIndex: 'herb_overview', width: 180, ellipsis: true },
          {
            title: '药方主治(文言文)',
            dataIndex: 'indication_original',
            width: 200,
            ellipsis: true,
          },
          {
            title: '现代主治(白话文)',
            dataIndex: 'indication_translation',
            width: 200,
            ellipsis: true,
          },
          { title: '拼音首拼', dataIndex: 'pinyin_initials', width: 100 },
          { title: '拼音全拼', dataIndex: 'pinyin', width: 120 },
          { title: '不存在的药品', key: 'missing', width: 180 },
        ]"
        :data-source="rows"
        :pagination="{ pageSize: 10, showSizeChanger: true }"
        size="small"
        :scroll="{ x: 1400 }"
        :row-class-name="(record) => (isAbnormalRow(record) ? 'gf-abnormal-row' : '')"
        row-key="name"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'abnormal'">
            <Tag v-if="isAbnormalRow(record)" color="error" class="!m-0">异常</Tag>
            <Tag v-else color="success" class="!m-0">正常</Tag>
          </template>
          <template v-else-if="column.key === 'missing'">
            <Tooltip
              v-if="rowMissingDrugs(record).length"
              :title="rowMissingDrugs(record).join('、')"
            >
              <span class="text-red-500">
                {{ rowMissingDrugs(record).join('、') }}
              </span>
            </Tooltip>
            <Tag v-else color="success" class="!m-0">齐全</Tag>
          </template>
        </template>
      </Table>
    </div>
  </Modal>
</template>
<style scoped>
/* 异常处方行：浅红底，暗色下用半透明红 */
:deep(.gf-abnormal-row) > td {
  background-color: hsl(var(--destructive) / 0.08) !important;
  color: hsl(var(--destructive));
}
</style>
