/* @vitest-environment happy-dom */

import type { VueWrapper } from '@vue/test-utils';
import type { Component } from 'vue';

import { mount } from '@vue/test-utils';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { defineComponent, getCurrentInstance, h, inject, nextTick, provide } from 'vue';

const modalMocks = vi.hoisted(() => ({
  auditPrint: vi.fn(),
  closeModal: vi.fn(),
  createConfirm: vi.fn(),
  downloadPdf: vi.fn(),
  openModal: vi.fn(),
  print: vi.fn(),
  register: vi.fn(),
  reload: vi.fn(),
  browserPrint: vi.fn(),
}));

vi.mock('#/router', () => ({
  router: {
    push: vi.fn(),
  },
}));

vi.mock('@jnpf/hooks', () => ({
  useGlobSetting: () => ({ apiURL: '' }),
  useMessage: () => ({
    createConfirm: modalMocks.createConfirm,
  }),
}));

vi.mock('@jnpf/ui/modal', async () => {
  const { defineComponent, h, onMounted } = await import('vue');

  return {
    BasicModal: defineComponent({
      name: 'BasicModal',
      emits: ['register'],
      props: {
        closeFunc: Function,
      },
      setup(_, { emit, slots }) {
        onMounted(() => emit('register'));

        return () =>
          h('section', { 'data-test': 'basic-modal' }, [
            h('header', { 'data-test': 'modal-title' }, slots.title?.()),
            h('main', { 'data-test': 'modal-content' }, slots.default?.()),
          ]);
      },
    }),
    useModal: () => [modalMocks.register, { closeModal: modalMocks.closeModal, openModal: modalMocks.openModal }],
  };
});

vi.mock('ant-design-vue', async () => {
  const { defineComponent, h } = await import('vue');

  return {
    Button: defineComponent({
      name: 'AButton',
      props: {
        danger: Boolean,
        disabled: Boolean,
        loading: Boolean,
        type: String,
      },
      emits: ['click'],
      setup(props, { emit, slots }) {
        return () =>
          h(
            'button',
            {
              disabled: props.disabled || props.loading,
              type: 'button',
              onClick: () => emit('click'),
            },
            slots.default?.(),
          );
      },
    }),
    Space: defineComponent({
      name: 'ASpace',
      setup(_, { slots }) {
        return () => h('div', { 'data-test': 'space' }, slots.default?.());
      },
    }),
    Spin: defineComponent({
      name: 'ASpin',
      setup(_, { slots }) {
        return () => h('div', slots.default?.());
      },
    }),
  };
});

vi.mock('#/components/CustomPrint/CustomPrintPreviewPane.vue', () => ({
  default: defineComponent({
    name: 'CustomPrintPreviewPane',
    emits: ['error', 'loaded', 'loading'],
    props: {
      config: {
        required: true,
        type: Object,
      },
    },
    setup(_, { expose }) {
      expose({
        browserPrint: modalMocks.browserPrint,
        downloadPdf: modalMocks.downloadPdf,
        hiprint: modalMocks.print,
        reload: modalMocks.reload,
      });

      return () => h('div', { 'data-test': 'custom-print-preview' });
    },
  }),
}));

vi.mock('../ReportAttachmentsPane.vue', () => ({
  default: defineComponent({
    name: 'ReportAttachmentsPane',
    setup() {
      return () => h('div', { 'data-test': 'attachments-pane' });
    },
  }),
}));

vi.mock('../ReportFormDetailPane.vue', () => ({
  default: defineComponent({
    name: 'ReportFormDetailPane',
    props: {
      tab: {
        required: true,
        type: Object,
      },
    },
    setup(props) {
      return () => h('div', { 'data-test': 'form-detail-pane' }, props.tab.id);
    },
  }),
}));

vi.mock('../ReportElnRecordsPane.vue', () => ({
  default: defineComponent({
    name: 'ReportElnRecordsPane',
    props: {
      tab: {
        required: true,
        type: Object,
      },
    },
    setup(props) {
      return () => h('div', { 'data-test': 'eln-records-pane' }, props.tab.qingyandanId);
    },
  }),
}));

import { onlineUtils } from '#/utils/jnpf';

import GlobalReportViewModal from '../index.vue';

const customPrintTab = {
  key: 'customPrint',
  print: {
    data: { id: 'record-id' },
    template: 'template-id',
  },
} as const;

function mountModal() {
  return mount(GlobalReportViewModal, {
    global: {
      components: {
        'a-tab-pane': defineComponent({
          name: 'ATabPane',
          props: {
            tab: String,
          },
          setup(props) {
            const instance = getCurrentInstance();
            const setActiveKey = inject<(key: string) => void>('setActiveKey');

            return () =>
              h(
                'div',
                {
                  'data-test': 'tab-pane',
                  onClick: () => setActiveKey?.(String(instance?.vnode.key)),
                },
                props.tab,
              );
          },
        }),
        'a-tabs': defineComponent({
          name: 'ATabs',
          emits: ['update:activeKey'],
          props: {
            activeKey: String,
          },
          setup(_, { emit, slots }) {
            provide('setActiveKey', (key: string) => emit('update:activeKey', key));

            return () => h('div', { 'data-test': 'tabs' }, slots.default?.());
          },
        }),
      },
    },
  });
}

async function openReportView(config = {}) {
  onlineUtils.openReportView({
    tabs: [customPrintTab],
    title: '查看报告',
    ...config,
  });

  await nextTick();
  await nextTick();
}

async function emitPrintLoaded(wrapper: VueWrapper) {
  wrapper.findComponent({ name: 'CustomPrintPreviewPane' }).vm.$emit('loaded');
  await nextTick();
}

function getButton(wrapper: VueWrapper, text: string) {
  const button = wrapper.findAll('button').find((item) => item.text() === text);

  expect(button, `button "${text}" exists`).toBeTruthy();
  return button!;
}

function queryButton(wrapper: VueWrapper, text: string) {
  return wrapper.findAll('button').find((item) => item.text() === text);
}

function getFormDetailText(wrapper: VueWrapper) {
  return wrapper.find('[data-test="form-detail-pane"]').text();
}

describe('GlobalReportViewModal interactions', () => {
  let wrapper: VueWrapper<Component> | null = null;

  beforeEach(() => {
    modalMocks.auditPrint.mockClear();
    modalMocks.closeModal.mockClear();
    modalMocks.createConfirm.mockClear();
    modalMocks.downloadPdf.mockReset();
    modalMocks.openModal.mockClear();
    modalMocks.print.mockImplementation((options) => {
      options?.onPrint?.({ mode: 'hiprint' });
      return Promise.resolve({ mode: 'hiprint' });
    });
    modalMocks.register.mockClear();
    modalMocks.reload.mockClear();
    modalMocks.browserPrint.mockClear();
    vi.spyOn(onlineUtils, 'auditPrint').mockImplementation(modalMocks.auditPrint);
    wrapper = mountModal();
  });

  afterEach(() => {
    wrapper?.unmount();
    wrapper = null;
    vi.restoreAllMocks();
  });

  it('无 actions 时显示默认打印按钮和关闭按钮', async () => {
    await openReportView();
    await emitPrintLoaded(wrapper!);

    expect(getButton(wrapper!, '导出PDF').attributes('disabled')).toBeUndefined();
    expect(getButton(wrapper!, '打印').attributes('disabled')).toBeUndefined();
    expect(getButton(wrapper!, '关闭').exists()).toBe(true);
  });

  it('有 actions 时显示业务动作且不显示默认打印按钮', async () => {
    await openReportView({
      actions: [
        {
          key: 'approve',
          label: '审核通过',
          onClick: vi.fn(),
          type: 'primary',
        },
      ],
    });

    expect(getButton(wrapper!, '审核通过').exists()).toBe(true);
    expect(queryButton(wrapper!, '导出PDF')).toBeUndefined();
    expect(queryButton(wrapper!, '打印')).toBeUndefined();
    expect(getButton(wrapper!, '关闭').exists()).toBe(true);
  });

  it('actions 为空数组时隐藏默认打印按钮', async () => {
    await openReportView({
      actions: [],
    });

    expect(queryButton(wrapper!, '导出PDF')).toBeUndefined();
    expect(queryButton(wrapper!, '打印')).toBeUndefined();
    expect(getButton(wrapper!, '关闭').exists()).toBe(true);
  });

  it('action 没有 confirmText 时点击后直接执行 action 且不弹确认', async () => {
    const onClick = vi.fn();

    await openReportView({
      actions: [
        {
          key: 'approve',
          label: '审核通过',
          onClick,
        },
      ],
    });

    await getButton(wrapper!, '审核通过').trigger('click');

    expect(modalMocks.createConfirm).not.toHaveBeenCalled();
    expect(onClick).toHaveBeenCalledTimes(1);
  });

  it('action 有 confirmText 时点击后弹出确认且不直接执行 action', async () => {
    const onClick = vi.fn();

    await openReportView({
      actions: [
        {
          confirmText: '确认审核通过吗？',
          key: 'approve',
          label: '审核通过',
          onClick,
        },
      ],
    });

    await getButton(wrapper!, '审核通过').trigger('click');

    expect(modalMocks.createConfirm).toHaveBeenCalledTimes(1);
    expect(modalMocks.createConfirm).toHaveBeenCalledWith(
      expect.objectContaining({
        content: '确认审核通过吗？',
      }),
    );
    expect(onClick).not.toHaveBeenCalled();

    const confirmOptions = modalMocks.createConfirm.mock.calls[0]?.[0] as { onOk: () => void } | undefined;
    expect(confirmOptions).toBeTruthy();
    confirmOptions!.onOk();
    await nextTick();

    expect(onClick).toHaveBeenCalledTimes(1);
  });

  it('点击打印时记录审计，Hiprint 导出PDF不重复记录', async () => {
    await openReportView();
    await emitPrintLoaded(wrapper!);

    await getButton(wrapper!, '打印').trigger('click');
    expect(modalMocks.print).toHaveBeenCalledTimes(1);
    expect(modalMocks.auditPrint).toHaveBeenCalledWith({
      bizType: undefined,
      printName: '报告',
      recordTitle: '报告',
      source: 'REPORT_VIEW',
      targetTable: undefined,
      targets: [{ id: 'record-id' }],
      templateId: undefined,
    });

    modalMocks.downloadPdf.mockResolvedValue(true);
    await getButton(wrapper!, '导出PDF').trigger('click');
    await nextTick();
    expect(modalMocks.downloadPdf).toHaveBeenCalledWith('查看报告');
    expect(modalMocks.browserPrint).not.toHaveBeenCalled();
    expect(modalMocks.print).toHaveBeenCalledTimes(1);
    expect(modalMocks.auditPrint).toHaveBeenCalledTimes(1);
  });

  it('Hiprint PDF 导出不可用时回退到浏览器打印且不记录审计', async () => {
    await openReportView();
    await emitPrintLoaded(wrapper!);
    modalMocks.downloadPdf.mockResolvedValue(false);

    await getButton(wrapper!, '导出PDF').trigger('click');
    await nextTick();

    expect(modalMocks.downloadPdf).toHaveBeenCalledWith('查看报告');
    expect(modalMocks.browserPrint).toHaveBeenCalledTimes(1);
    expect(modalMocks.auditPrint).not.toHaveBeenCalled();
  });

  it('customPrint 支持显式审计字段映射，也可关闭审计', async () => {
    await openReportView({
      tabs: [
        {
          key: 'customPrint',
          print: {
            audit: {
              bizCodeField: 'report.code',
              bizType: 'SAMPLE_REPORT',
              idField: 'report.id',
              printName: '检验报告',
              recordTitle: '报告打印',
              targetTable: 'lims_sample_report',
              templateId: 'template-id',
              titleField: 'report.title',
            },
            data: { report: { code: 'BG-001', id: 'record-1', title: '第一份报告' } },
            template: 'template-id',
          },
        },
      ],
    });
    await emitPrintLoaded(wrapper!);

    await getButton(wrapper!, '打印').trigger('click');

    expect(modalMocks.auditPrint).toHaveBeenCalledWith({
      bizType: 'SAMPLE_REPORT',
      printName: '检验报告',
      recordTitle: '报告打印',
      source: 'REPORT_VIEW',
      targetTable: 'lims_sample_report',
      targets: [{ bizCode: 'BG-001', id: 'record-1', title: '第一份报告' }],
      templateId: 'template-id',
    });

    await openReportView({
      tabs: [{ key: 'customPrint', print: { audit: false, data: { id: 'record-2' }, template: 'template-id' } }],
    });
    await emitPrintLoaded(wrapper!);
    modalMocks.auditPrint.mockClear();

    await getButton(wrapper!, '打印').trigger('click');

    expect(modalMocks.auditPrint).not.toHaveBeenCalled();
  });

  it('打印渲染数据没有主键时使用同一报告的 formDetail id', async () => {
    await openReportView({
      activeKey: 'customPrint',
      tabs: [
        {
          id: 'business-record-id',
          key: 'formDetail',
          modelId: 'model-id',
          title: '报告详情',
        },
        {
          key: 'customPrint',
          print: {
            data: { reportBody: { title: '稳定性考察报告' } },
            template: 'wendingxing_huizong',
            title: '汇总',
          },
          title: '查看报告',
        },
      ],
    });
    await emitPrintLoaded(wrapper!);

    await getButton(wrapper!, '打印').trigger('click');

    expect(modalMocks.auditPrint).toHaveBeenCalledWith(
      expect.objectContaining({
        printName: '汇总',
        source: 'REPORT_VIEW',
        targets: [{ id: 'business-record-id' }],
      }),
    );
  });

  it('onlineUtils.closeReportView 连续触发时只关闭一次并只调用一次 onClose', async () => {
    const onClose = vi.fn();

    await openReportView({ onClose });

    onlineUtils.closeReportView();
    onlineUtils.closeReportView();

    expect(modalMocks.closeModal).toHaveBeenCalledTimes(1);
    expect(onClose).toHaveBeenCalledTimes(1);
  });

  it('点击关闭按钮后再次触发 closeReportView 仍只关闭一次', async () => {
    const onClose = vi.fn();

    await openReportView({ onClose });

    await getButton(wrapper!, '关闭').trigger('click');
    onlineUtils.closeReportView();

    expect(modalMocks.closeModal).toHaveBeenCalledTimes(1);
    expect(onClose).toHaveBeenCalledTimes(1);
  });

  it('unmount 后清理 report view 事件监听', async () => {
    await openReportView();

    expect(modalMocks.openModal).toHaveBeenCalledTimes(1);

    wrapper!.unmount();
    wrapper = null;

    onlineUtils.openReportView({
      tabs: [customPrintTab],
      title: '卸载后打开',
    });
    onlineUtils.closeReportView();

    await nextTick();
    await nextTick();

    expect(modalMocks.openModal).toHaveBeenCalledTimes(1);
    expect(modalMocks.closeModal).not.toHaveBeenCalled();
  });

  it('loaded 前打印按钮 disabled，loaded 后启用', async () => {
    await openReportView();

    expect(getButton(wrapper!, '打印').attributes('disabled')).toBeDefined();

    await emitPrintLoaded(wrapper!);

    expect(getButton(wrapper!, '打印').attributes('disabled')).toBeUndefined();
  });

  it('支持在多个 formDetail tab 之间切换', async () => {
    await openReportView({
      activeKey: 'formDetail',
      tabs: [
        {
          id: 'form-id-1',
          key: 'formDetail',
          modelId: 'model-id-1',
          title: '委托信息',
        },
        {
          id: 'form-id-2',
          key: 'formDetail',
          modelId: 'model-id-2',
          title: '检验记录',
        },
      ],
    });

    expect(wrapper!.findAll('[data-test="tab-pane"]').map((item) => item.text())).toEqual(['委托信息', '检验记录']);
    expect(getFormDetailText(wrapper!)).toContain('form-id-1');

    await wrapper!.findAll('[data-test="tab-pane"]')[1]!.trigger('click');

    expect(getFormDetailText(wrapper!)).toContain('form-id-2');
  });

  it('renders the ELN records pane for an elnRecords tab', async () => {
    await openReportView({
      tabs: [{ key: 'elnRecords', qingyandanId: 'request-1', title: '电子记录' }],
    });

    expect(wrapper!.get('[data-test="eln-records-pane"]').text()).toBe('request-1');
  });
});
