<script lang="ts" setup>
/**
 * 金方库管理：CRUD + Excel 导入 + 药方设置 + 缺失药品
 * VIP 功能码 golden_formula 由「VIP等级配置」勾选分配，本页只管平台金方数据
 */
import type { VxeGridListeners } from '#/adapter/vxe-table';

import { ref } from 'vue';

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

import { Tag, message, Modal as AntModal } from 'ant-design-vue';

import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { TableAction } from '#/components/table-action';
import { downloadByData } from '#/util/tool';

import {
  deleteGoldenFormula,
  getGoldenFormulaList,
  importGoldenFormula,
} from './api';
import FormModal from './components/modal.vue';
import ImportExcelModal from './components/ImportExcelModal.vue';
import ImportPreviewModal from './components/ImportPreviewModal.vue';
import FormulaDrugsModal from './components/FormulaDrugsModal.vue';
import MissingDrugModal from './components/MissingDrugModal.vue';
import { ABNORMAL_FILTER_OPTIONS, STATUS_OPTIONS } from './config/constants';
import { exportGoldenFormulaTemplate } from './utils/exportGoldenFormulaExcel';
import { parseGoldenFormulaExcelBuffer } from './utils/parseGoldenFormulaExcel';

defineOptions({ name: 'GoldenFormula' });

const hasTopTableDropDownActions = ref(false);
const importing = ref(false);

const [Grid, gridApi] = useVbenVxeGrid({
  formOptions: {
    schema: [
      {
        component: 'VbenInput',
        fieldName: 'name',
        label: '药方名字',
        componentProps: { placeholder: '名称/首拼/速览' },
      },
      {
        component: 'VbenInput',
        fieldName: 'source',
        label: '来源',
        componentProps: { placeholder: '金方来源' },
      },
      {
        component: 'VbenSelect',
        fieldName: 'status',
        label: '状态',
        componentProps: { allowClear: true, options: STATUS_OPTIONS },
      },
      {
        component: 'VbenSelect',
        fieldName: 'is_abnormal',
        label: '异常标记',
        componentProps: {
          allowClear: true,
          options: ABNORMAL_FILTER_OPTIONS,
        },
      },
    ],
  },
  gridOptions: {
    checkboxConfig: { highlight: true, labelField: '' },
    columns: [
      { type: 'checkbox', width: 60 },
      { field: 'id', title: 'ID', width: 80 },
      {
        field: 'name',
        title: '药方名字',
        minWidth: 140,
        slots: { default: 'name' },
      },
      { field: 'clause_number', title: '条文编号', width: 110 },
      {
        field: 'source_name',
        title: '来源',
        width: 120,
        slots: { default: 'source_name' },
      },
      { field: 'herb_overview', title: '药材速览', minWidth: 180 },
      { field: 'drug_count', title: '药味数', width: 80 },
      {
        field: 'is_abnormal',
        title: '异常',
        width: 110,
        slots: { default: 'is_abnormal' },
      },
      { field: 'pinyin_initials', title: '首拼', width: 100 },
      { field: 'status', title: '状态', width: 90, slots: { default: 'status' } },
      { field: 'sort', title: '排序', width: 80 },
      { field: 'created_at', title: '创建时间', width: 170 },
      { title: '操作', slots: { default: 'action' }, width: 220, fixed: 'right' },
    ],
    keepSource: true,
    pagerConfig: {},
    proxyConfig: {
      ajax: {
        query: async ({ page }: any, formValues: any) => {
          return await getGoldenFormulaList({
            page: page.currentPage,
            pageSize: page.pageSize,
            ...formValues,
          });
        },
      },
    },
    height: 'auto',
    toolbarConfig: {
      search: true,
      refresh: true,
      slots: { buttons: 'toolbar-actions' },
    },
  },
  gridEvents: {
    checkboxChange() {
      hasTopTableDropDownActions.value =
        gridApi.grid.getCheckboxRecords().length > 0;
    },
    checkboxAll() {
      hasTopTableDropDownActions.value =
        gridApi.grid.getCheckboxRecords().length > 0;
    },
  } as VxeGridListeners<any>,
});

const [FormModalComp, formModalApi] = useVbenModal({
  connectedComponent: FormModal,
});

/** 导入选文件弹窗：拖拽 / 点击 / 粘贴 */
const [ImportExcelModalComp, importExcelApi] = useVbenModal({
  connectedComponent: ImportExcelModal,
});

/** 导入预览弹窗：解析后预览 + 选金方来源 + 确认导入 */
const [ImportPreviewModalComp, importPreviewApi] = useVbenModal({
  connectedComponent: ImportPreviewModal,
});

/** 药方设置：独立编辑组成 */
const [FormulaDrugsModalComp, formulaDrugsModalApi] = useVbenModal({
  connectedComponent: FormulaDrugsModal,
});

/** 缺失药品清单 */
const [MissingDrugModalComp, missingDrugModalApi] = useVbenModal({
  connectedComponent: MissingDrugModal,
});

const showModal = (data: any = {}, isUpdate = false) => {
  formModalApi.setData({
    values: data,
    update: isUpdate,
    gridApi,
  });
  formModalApi.open();
};

/** 打开药方设置弹窗 */
const showFormulaDrugsModal = (row: any) => {
  formulaDrugsModalApi.setData({
    id: Number(row?.id || 0),
    gridApi,
  });
  formulaDrugsModalApi.open();
};

/** 打开缺失药品弹窗 */
const showMissingDrugModal = () => {
  missingDrugModalApi.open();
};

const handleDelete = async (ids: number[]) => {
  await deleteGoldenFormula({ ids });
  message.success('删除成功');
  gridApi.query();
};

async function handleDownloadTemplate() {
  const buffer = await exportGoldenFormulaTemplate();
  downloadByData(
    buffer,
    '金方导入模板.xlsx',
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  );
}

/** 打开导入选文件弹窗（不再直接调起系统文件选择） */
function openImportExcelModal() {
  importExcelApi.setData({
    onConfirmFile: handleImportFile,
  });
  importExcelApi.open();
}

/**
 * 解析 Excel → 打开展示预览（由导入选文件弹窗确认后调用）
 */
async function handleImportFile(file: File) {
  importing.value = true;
  try {
    const buffer = await file.arrayBuffer();
    const parsed = await parseGoldenFormulaExcelBuffer(buffer);
    if (!parsed.items.length) {
      const detail = parsed.firstInvalidReason
        ? `：${parsed.firstInvalidReason}`
        : '';
      // warning 已提示用户；抛错仅用于保持选文件弹窗不关闭
      message.warning(
        parsed.invalidCount
          ? `没有可导入的有效行（无效 ${parsed.invalidCount} 行）${detail}`
          : '文件无有效数据，请确认填写的是「金方导入」工作表',
      );
      throw new Error('__import_empty__');
    }
    // 打开预览弹窗：用户选金方来源 + 确认后再提交
    importPreviewApi.setData({ rows: parsed.items });
    importPreviewApi.open();
  } catch (e: any) {
    if (e?.message !== '__import_empty__') {
      message.error(e?.message || '解析失败');
    }
    throw e;
  } finally {
    importing.value = false;
  }
}

/**
 * 预览弹窗确认后：带 source_id 提交导入，弹结果框
 */
async function handleConfirmImport(payload: { rows: any[]; sourceId: number }) {
  importing.value = true;
  try {
    const res = await importGoldenFormula({
      rows: payload.rows,
      source_id: payload.sourceId,
    });
    const ok = Number(res?.success || 0);
    const fail = Number(res?.fail || 0);
    const missingCount = Number(res?.missing_count || 0);
    const errors = Array.isArray(res?.errors) ? res.errors : [];
    AntModal.info({
      title: '导入结果',
      content: `成功 ${ok} 条，失败 ${fail} 条${
        missingCount > 0 ? `，缺失药名 ${missingCount} 个（已写入缺失药品表）` : ''
      }${errors.length ? `\n${errors.slice(0, 10).join('\n')}` : ''}`,
      width: 520,
    });
    gridApi.reload();
  } catch (e: any) {
    message.error(e?.message || '导入失败');
  } finally {
    importing.value = false;
  }
}
</script>
<template>
  <Page auto-content-height title="金方管理">
    <FormModalComp />
    <ImportExcelModalComp />
    <ImportPreviewModalComp @confirm="handleConfirmImport" />
    <FormulaDrugsModalComp />
    <MissingDrugModalComp />
    <Grid>
      <template #toolbar-actions>
        <TableAction
          :flex="false"
          :actions="[
            {
              label: '新增',
              type: 'primary',
              onClick: () => showModal({}, false),
            },
            {
              label: '下载模板',
              onClick: handleDownloadTemplate,
            },
            {
              label: '导入 Excel',
              loading: importing,
              onClick: openImportExcelModal,
            },
            {
              label: '缺失药品',
              onClick: showMissingDrugModal,
            },
            {
              label: '批量删除',
              danger: true,
              disabled: !hasTopTableDropDownActions,
              popConfirm: {
                title: '确认删除选中金方？',
                confirm: () => {
                  const rows = gridApi.grid.getCheckboxRecords();
                  handleDelete(rows.map((r: any) => r.id));
                },
              },
            },
          ]"
        />
      </template>
      <!-- 异常处方：药方名字整列标红 -->
      <template #name="{ row }">
        <span :class="{ 'gf-name-abnormal': row.is_abnormal === 1 }">
          {{ row.name }}
        </span>
      </template>
      <template #source_name="{ row }">
        {{ row.source_name || row.source || '—' }}
      </template>
      <template #is_abnormal="{ row }">
        <span class="gf-flag-cell">
          <Tag v-if="row.is_abnormal === 1" color="error">异常</Tag>
          <Tag v-if="row.has_unmatched === 1" color="warning">未匹配</Tag>
          <Tag
            v-if="row.is_abnormal !== 1 && row.has_unmatched !== 1"
            color="success"
          >
            正常
          </Tag>
        </span>
      </template>
      <template #status="{ row }">
        <Tag :color="row.status === 1 ? 'success' : 'default'">
          {{ row.status === 1 ? '启用' : '禁用' }}
        </Tag>
      </template>
      <template #action="{ row }">
        <TableAction
          :actions="[
            {
              label: '编辑',
              onClick: () => showModal(row, true),
            },
            {
              label: '药方设置',
              onClick: () => showFormulaDrugsModal(row),
            },
            {
              label: '删除',
              danger: true,
              popConfirm: {
                title: '确认删除该金方？',
                confirm: () => handleDelete([row.id]),
              },
            },
          ]"
        />
      </template>
    </Grid>
  </Page>
</template>
<style scoped>
/* 异常处方药方名字：用主题 destructive 色，暗色下可读 */
.gf-name-abnormal {
  color: hsl(var(--destructive));
  font-weight: 600;
}
.gf-flag-cell {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
}
</style>
