<template>
  <div>
    <BasicTable @register="registerTable" :rowSelection="rowSelection">
      <template #tableTitle>
        <a-button type="primary" v-auth="'mes:mes_raw_material_inspect_std:add'" @click="handleAdd" preIcon="ant-design:plus-outlined">
          新增
        </a-button>
        <JDictSelectTag
          v-model:value="printDotWsUrl"
          dictCode="xslmes_print_dot_ws"
          :showChooseOption="false"
          style="width: 280px; margin-left: 8px"
          placeholder="选择 PrintDot 地址"
          @change="onPrintDotWsUrlChange"
        />
        <a-button v-if="!printDotConnected" style="margin-left: 8px" @click="downloadPrintPlugin">下载打印插件</a-button>
        <a-select
          v-model:value="selectedPrinterName"
          :options="printerOptions"
          style="width: 220px; margin-left: 8px"
          allow-clear
          show-search
          option-filter-prop="label"
          :placeholder="printerSelectPlaceholder"
        />
        <a-button style="margin-left: 8px" @click="() => refreshPrinterOptions(true)">刷新打印机</a-button>
        <a-button
          type="primary"
          ghost
          v-auth="'mes:mes_raw_material_inspect_std:edit'"
          :loading="printLoading"
          :disabled="selectedRowKeys.length === 0"
          @click="handlePrintSelected"
        >
          <Icon icon="ant-design:printer-outlined" />
          打印选中
        </a-button>
      </template>
      <template #action="{ record }">
        <TableAction
          :actions="getTableAction(record)"
          :dropDownActions="getDropDownAction(record)"
        />
      </template>
    </BasicTable>
    <MesRawMaterialInspectStdModal @register="registerModal" @success="reload" />
    <MesRawMaterialInspectStdPrintPreviewModal
      v-model:open="printPreviewOpen"
      :std-id="printPreviewStdId"
      :standard-no="printPreviewStandardNo"
    />
  </div>
</template>
<script lang="ts" setup>
  import { onMounted, ref, watch } from 'vue';
  import { Icon } from '/@/components/Icon';
  import { BasicTable, TableAction } from '/@/components/Table';
  import { useModal } from '/@/components/Modal';
  import { useListPage } from '/@/hooks/system/useListPage';
  import { initDictOptions } from '/@/utils/dict';
  import { JDictSelectTag } from '/@/components/Form';
  import MesRawMaterialInspectStdModal from './modules/MesRawMaterialInspectStdModal.vue';
  import MesRawMaterialInspectStdPrintPreviewModal from './modules/MesRawMaterialInspectStdPrintPreviewModal.vue';
  import { columns, searchFormSchema } from './MesRawMaterialInspectStd.data';
  import { list, deleteOne, setEnable, prepareNativePrint } from './MesRawMaterialInspectStd.api';
  import { useMessage } from '/@/hooks/web/useMessage';
  import {
    PRINT_TEMPLATE_SELECTED_PRINTER_KEY,
    printNativeSchemaViaPrintDot,
  } from '/@/views/print/template/utils/printNativeViaPrintDot';
  import { normalizeImportedNativeSchema } from '/@/views/print/template/native/core/nativeSchemaNormalize';
  import {
    fetchPrintDotPrinters,
    getPrintDotBridgeConfig,
    setPrintDotBridgeConfig,
  } from '/@/views/print/template/utils/printDotBridge';

  const { createMessage } = useMessage();
  const PRINT_DOT_WS_DICT = 'xslmes_print_dot_ws';
  const printDotWsUrl = ref('');
  const printDotConnected = ref(false);

  function persistPrintDotConfig() {
    setPrintDotBridgeConfig(String(printDotWsUrl.value || '').trim(), '');
    void refreshPrinterOptions(false);
  }

  function onPrintDotWsUrlChange() {
    printDotConnected.value = false;
    persistPrintDotConfig();
  }

  function downloadPrintPlugin() {
    const base = import.meta.env.BASE_URL || '/';
    const normalizedBase = base.endsWith('/') ? base : `${base}/`;
    const url = `${normalizedBase}print-plugin/XSL-PrintDot.exe`;
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', 'XSL-PrintDot.exe');
    link.rel = 'noopener';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  }

  const [registerModal, { openModal }] = useModal();
  const { tableContext } = useListPage({
    tableProps: {
      title: '原材料检验标准',
      api: list,
      columns,
      canResize: true,
      formConfig: { labelWidth: 100, schemas: searchFormSchema, autoSubmitOnEnter: true },
      actionColumn: { width: 280, fixed: 'right' },
    },
  });
  const [registerTable, { reload }, { rowSelection, selectedRowKeys, selectedRows }] = tableContext;

  const printPreviewOpen = ref(false);
  const printPreviewStdId = ref<string | null>(null);
  const printPreviewStandardNo = ref<string | undefined>(undefined);

  function handlePrintPreview(record: Recordable) {
    printPreviewStdId.value = record.id as string;
    printPreviewStandardNo.value = record.standardNo as string | undefined;
    printPreviewOpen.value = true;
  }

  const printerOptions = ref<Array<{ label: string; value: string }>>([]);
  const selectedPrinterName = ref<string>('__system_default__');
  const printLoading = ref(false);
  const PRINT_ROW_LOADING_KEY = 'mesRawMaterialInspectStd-print-row';
  const PRINT_BATCH_LOADING_KEY = 'mesRawMaterialInspectStd-print-batch';
  const printerSelectPlaceholder = '选择打印机（PrintDot 桥接）';

  watch(selectedPrinterName, (v) => {
    if (v) {
      localStorage.setItem(PRINT_TEMPLATE_SELECTED_PRINTER_KEY, v);
    }
  });

  async function refreshPrinterOptions(showMessage = true) {
    const optionMap = new Map<string, { label: string; value: string }>();
    optionMap.set('__system_default__', { label: '系统默认打印机', value: '__system_default__' });
    try {
      const dotList = await fetchPrintDotPrinters();
      printDotConnected.value = true;
      dotList.forEach((p) => {
        const name = String(p.name || '').trim();
        if (!name) return;
        const defMark = p.isDefault ? '（默认）' : '';
        optionMap.set(name, { label: `${name}${defMark}`, value: name });
      });
      printerOptions.value = Array.from(optionMap.values());
      if (showMessage) {
        if (dotList.length) {
          createMessage.success(`已从 PrintDot 桥接识别 ${dotList.length} 台打印机`);
        } else {
          createMessage.warning('PrintDot 已连接但未返回打印机列表');
        }
      }
    } catch (e: unknown) {
      printDotConnected.value = false;
      printerOptions.value = Array.from(optionMap.values());
      if (showMessage) {
        createMessage.warning(`PrintDot：${e instanceof Error ? e.message : String(e)}`);
      }
    }
  }

  async function executePrint(record: Recordable, options?: { silentSuccess?: boolean }) {
    try {
      const prep = (await prepareNativePrint(record.id as string)) as Record<string, unknown>;
      const templateJsonRaw = prep.templateJson as string;
      const printData = prep.printData as Record<string, unknown>;
      const paperWidthMm = Number((prep as any).paperWidthMm ?? 0);
      const paperHeightMm = Number((prep as any).paperHeightMm ?? 0);
      const paperOrientation = String((prep as any).paperOrientation || '').toLowerCase();
      if (!templateJsonRaw) {
        throw new Error('模板 JSON 为空');
      }
      let raw: unknown;
      try {
        raw = typeof templateJsonRaw === 'string' ? JSON.parse(templateJsonRaw) : templateJsonRaw;
      } catch {
        throw new Error('模板 JSON 格式错误');
      }
      const schema = normalizeImportedNativeSchema(raw);
      if (paperWidthMm > 0 && paperHeightMm > 0) {
        const orient = paperOrientation === 'landscape' ? 'landscape' : paperOrientation === 'portrait' ? 'portrait' : '';
        const normalized =
          orient === 'landscape'
            ? {
                width: Math.max(paperWidthMm, paperHeightMm),
                height: Math.min(paperWidthMm, paperHeightMm),
              }
            : orient === 'portrait'
              ? {
                  width: Math.min(paperWidthMm, paperHeightMm),
                  height: Math.max(paperWidthMm, paperHeightMm),
                }
              : {
                  width: paperWidthMm,
                  height: paperHeightMm,
                };
        schema.page.width = normalized.width;
        schema.page.height = normalized.height;
      }
      const no = String(record.standardNo || '').trim();
      await printNativeSchemaViaPrintDot({
        schema,
        data: printData as Record<string, unknown>,
        jobName: `原材料检验标准-${no || record.id}.pdf`,
        printerSelection:
          selectedPrinterName.value ||
          localStorage.getItem(PRINT_TEMPLATE_SELECTED_PRINTER_KEY) ||
          '__system_default__',
      });
      if (!options?.silentSuccess) {
        createMessage.success('已通过 PrintDot 提交打印');
      }
    } catch (e: unknown) {
      throw new Error(e instanceof Error ? e.message : String(e));
    }
  }

  function handlePrintSelected() {
    const rows = selectedRows.value || [];
    if (!rows.length) {
      createMessage.warning('请至少勾选一条记录后再点击「打印选中」');
      return;
    }
    printLoading.value = true;
    createMessage.destroy(PRINT_BATCH_LOADING_KEY);
    createMessage.loading({
      content: `正在打印 ${rows.length} 条记录，请稍候…`,
      key: PRINT_BATCH_LOADING_KEY,
      duration: 0,
    });
    (async () => {
      try {
        let ok = 0;
        let firstError = '';
        for (const row of rows) {
          try {
            await executePrint(row, { silentSuccess: true });
            ok += 1;
          } catch (e: unknown) {
            if (!firstError) {
              firstError = e instanceof Error ? e.message : String(e);
            }
          }
        }
        if (ok === rows.length) {
          createMessage.success(`已通过 PrintDot 提交 ${ok} 条打印任务`);
        } else {
          createMessage.warning(
            `打印完成：成功 ${ok}，失败 ${rows.length - ok}${firstError ? `。首条错误：${firstError}` : ''}`,
          );
        }
      } finally {
        createMessage.destroy(PRINT_BATCH_LOADING_KEY);
        printLoading.value = false;
      }
    })();
  }

  async function handlePrintRow(record: Recordable) {
    printLoading.value = true;
    createMessage.destroy(PRINT_ROW_LOADING_KEY);
    createMessage.loading({
      content: '正在生成 PDF 并提交打印，版面复杂时可能需数十秒，请稍候…',
      key: PRINT_ROW_LOADING_KEY,
      duration: 0,
    });
    try {
      await executePrint(record, { silentSuccess: true });
      createMessage.success('已通过 PrintDot 提交打印');
    } catch (e: unknown) {
      createMessage.error(e instanceof Error ? e.message : String(e));
    } finally {
      createMessage.destroy(PRINT_ROW_LOADING_KEY);
      printLoading.value = false;
    }
  }

  onMounted(async () => {
    const cfg = getPrintDotBridgeConfig();
    setPrintDotBridgeConfig(cfg.wsUrl, '');
    printDotWsUrl.value = cfg.wsUrl || '';

    try {
      const raw = await initDictOptions(PRINT_DOT_WS_DICT);
      const items = Array.isArray(raw) ? raw : [];
      const values = items
        .map((it: Recordable) => String(it.value ?? it.itemValue ?? '').trim())
        .filter(Boolean);
      const valueSet = new Set(values);
      if (valueSet.size && printDotWsUrl.value && !valueSet.has(String(printDotWsUrl.value).trim())) {
        printDotWsUrl.value = values[0];
        setPrintDotBridgeConfig(printDotWsUrl.value, '');
      } else if (valueSet.size && !printDotWsUrl.value.trim()) {
        printDotWsUrl.value = values[0];
        setPrintDotBridgeConfig(printDotWsUrl.value, '');
      }
    } catch {
      /* 字典未配置时沿用 localStorage */
    }

    const savedPrinter = localStorage.getItem(PRINT_TEMPLATE_SELECTED_PRINTER_KEY);
    if (savedPrinter) {
      selectedPrinterName.value = savedPrinter;
    }
    await refreshPrinterOptions(false);
  });

  function handleAdd() {
    openModal(true, { isUpdate: false, showFooter: true });
  }
  function handleEdit(record: Recordable) {
    openModal(true, { record, isUpdate: true, showFooter: true });
  }
  function handleDetail(record: Recordable) {
    openModal(true, { record, isUpdate: true, showFooter: false });
  }
  async function handleDelete(record) {
    await deleteOne({ id: record.id }, reload);
  }
  async function handleEnable(record: Recordable) {
    await setEnable({ id: record.id, enableFlag: 1 });
    createMessage.success('已启用');
    reload();
  }
  async function handleDisable(record: Recordable) {
    await setEnable({ id: record.id, enableFlag: 0 });
    createMessage.success('已停用');
    reload();
  }

  function getTableAction(record: Recordable) {
    return [
      {
        label: '编辑',
        onClick: handleEdit.bind(null, record),
        auth: 'mes:mes_raw_material_inspect_std:edit',
      },
      {
        label: '打印预览',
        onClick: handlePrintPreview.bind(null, record),
        auth: 'mes:mes_raw_material_inspect_std:edit',
      },
      {
        label: '打印',
        onClick: handlePrintRow.bind(null, record),
        auth: 'mes:mes_raw_material_inspect_std:edit',
      },
    ];
  }

  function getDropDownAction(record: Recordable) {
    const actions: any[] = [
      { label: '详情', onClick: handleDetail.bind(null, record) },
      {
        label: '删除',
        popConfirm: { title: '是否确认删除', confirm: handleDelete.bind(null, record) },
        auth: 'mes:mes_raw_material_inspect_std:delete',
      },
    ];
    if (record.enableFlag !== 1) {
      actions.push({
        label: '启用',
        auth: 'mes:mes_raw_material_inspect_std:enable',
        popConfirm: { title: '启用后将记录当前时间到生效日期', confirm: () => handleEnable(record) },
      });
    } else {
      actions.push({
        label: '停用',
        auth: 'mes:mes_raw_material_inspect_std:enable',
        popConfirm: { title: '停用后将清除生效日期', confirm: () => handleDisable(record) },
      });
    }
    return actions;
  }
</script>
