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

import { Download, Printer } from '@vben/icons';
import { $t } from '@vben/locales';
import { ReportDialogHeader, ZqUniverPrint } from '@zq/univer';
import '@zq/univer/style';

import UniverHost from '../univer-host.vue';

import { ElButton, ElDialog, ElMessage, ElMessageBox } from 'element-plus';

import {
  exportReportDesignExcelApi,
  previewReportDesignApi,
} from '#/api/online-dev/report-manager';
import { useReportQuery } from '#/components/report-design/hooks/useReportQuery';
import ReportQueryForm from '#/components/report-design/modules/report-query-form.vue';
import { countSnapshotImages } from '#/components/report-design/utils/report-media-url';
import { showPreviewWarnings } from '#/components/report-design/utils/preview-warnings';

const visible = defineModel<boolean>('visible', { default: false });

const props = defineProps<{
  versionId: string;
  reportCode?: string;
  reportName?: string;
  queryList: any[];
  getDraftPayload?: () => Record<string, any> | null | undefined;
}>();

const loading = ref(false);
const exportLoading = ref(false);
const allowExport = ref(true);
const allowPrint = ref(true);
const printRef = ref<InstanceType<typeof ZqUniverPrint> | null>(null);
const previewReady = ref(false);
const previewSessionKey = ref(0);
const previewSnapshot = ref<Record<string, any>>({});
const previewCells = ref<Record<string, any>>({});
const previewChartData = ref<any[]>([]);
const previewWatermark = ref<{ show?: boolean; config?: Record<string, any> }>({
  show: false,
  config: {},
});

const { searchSchemas, formValues, setQueryList, getDefaultParams, setFormValues } =
  useReportQuery();

watch(
  () => props.queryList,
  (list) => setQueryList(list || []),
  { immediate: true },
);

function resetPreviewState() {
  previewReady.value = false;
  allowExport.value = true;
  allowPrint.value = true;
  previewSnapshot.value = {};
  previewCells.value = {};
  previewChartData.value = [];
  previewWatermark.value = { show: false, config: {} };
}

watch(visible, async (v) => {
  if (!v) {
    resetPreviewState();
    return;
  }
  if (!props.versionId) return;

  resetPreviewState();
  await runPreview();
  previewSessionKey.value += 1;
  previewReady.value = true;
});

function buildDraftPayload() {
  const draft = props.getDraftPayload?.();
  if (!draft) return undefined;
  return {
    snapshot: draft.snapshot,
    cells: draft.cells,
    queryList: draft.queryList,
    sortList: draft.sortList,
    columnList: draft.columnList,
    fenceList: draft.fenceList,
    convertConfig: draft.convertConfig,
  };
}

async function runPreview() {
  if (!props.versionId) return;
  loading.value = true;
  try {
    const res = await previewReportDesignApi(
      props.versionId,
      getDefaultParams(),
      buildDraftPayload(),
    );
    previewSnapshot.value = res.snapshot || {};
    previewCells.value = res.cells || {};
    previewChartData.value = Array.isArray(res.chartData)
      ? res.chartData
      : [];
    previewWatermark.value =
      res.watermark && typeof res.watermark === 'object'
        ? res.watermark
        : {
            show: !!res.allowWatermark,
            config: res.watermarkConfig || {},
          };
    allowExport.value = res.allowExport !== false;
    allowPrint.value = res.allowPrint !== false;
    showPreviewWarnings(Array.isArray(res.warnings) ? res.warnings : []);
  } finally {
    loading.value = false;
  }
}

async function handleExportExcel() {
  if (exportLoading.value || !props.versionId) return;
  if (!allowExport.value) {
    ElMessage.warning($t('report-manager.export.notAllowed'));
    return;
  }
  exportLoading.value = true;
  try {
    const blob = await exportReportDesignExcelApi(
      props.versionId,
      getDefaultParams(),
      buildDraftPayload(),
    );
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${props.reportCode || props.reportName || 'report'}.xlsx`;
    a.click();
    URL.revokeObjectURL(url);
    ElMessage.success($t('report-manager.export.success'));
  } catch (error: any) {
    ElMessage.error(error?.message || $t('report-manager.export.failed'));
  } finally {
    exportLoading.value = false;
  }
}

async function handlePrint() {
  if (!allowPrint.value) {
    ElMessage.warning($t('report-manager.print.notAllowed'));
    return;
  }
  if (!previewSnapshot.value || !Object.keys(previewSnapshot.value).length) {
    ElMessage.warning($t('report-manager.render.empty'));
    return;
  }

  const imageCount = countSnapshotImages(previewSnapshot.value, previewCells.value);
  if (imageCount > 100) {
    try {
      await ElMessageBox.confirm(
        $t('report-manager.print.imageWarn', { count: imageCount }),
        $t('report-manager.print.title'),
        { type: 'warning' },
      );
    } catch {
      return;
    }
  }

  printRef.value?.handleCreatePrintUnit?.({
    snapshot: previewSnapshot.value as any,
    watermarkConfig: previewWatermark.value,
    reportName: props.reportName,
    reportCode: props.reportCode,
  });
}

function handleClose() {
  visible.value = false;
}
</script>

<template>
  <ElDialog
    v-model="visible"
    class="report-preview-dialog"
    fullscreen
    append-to-body
    destroy-on-close
    :show-close="false"
    :close-on-click-modal="false"
  >
    <div class="bg-background flex h-full min-h-0 flex-col">
      <ReportDialogHeader
        :report-name="reportName"
        :report-code="reportCode"
        :fallback-title="$t('report-manager.preview.title')"
      >
        <template #actions>
          <ElButton
            v-if="allowExport"
            :icon="Download"
            :loading="exportLoading"
            @click="handleExportExcel"
          >
            {{ $t('report-manager.export.title') }}
          </ElButton>
          <ElButton v-if="allowPrint" :icon="Printer" @click="handlePrint">
            {{ $t('report-manager.print.title') }}
          </ElButton>
          <ElButton @click="handleClose">
            {{ $t('common.close') }}
          </ElButton>
        </template>
      </ReportDialogHeader>

      <main
        v-loading="loading"
        class="report-preview-dialog__content m-3 min-h-0 min-w-0 flex-1 overflow-hidden rounded-lg"
      >
        <ReportQueryForm
          :schemas="searchSchemas"
          :model-value="formValues"
          :loading="loading"
          @update:model-value="setFormValues"
          @search="runPreview"
        />
        <div class="report-preview-dialog__sheet">
          <UniverHost
            v-if="previewReady"
            :key="previewSessionKey"
            mode="preview"
            readonly
            class="h-full w-full"
            :snapshot="previewSnapshot"
            :cells="previewCells"
            :chart-data="previewChartData"
            :watermark="previewWatermark"
          />
        </div>
      </main>
    </div>
  </ElDialog>

  <Teleport to="body">
    <ZqUniverPrint ref="printRef" />
  </Teleport>
</template>

<style lang="scss">
.report-preview-dialog.el-dialog {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;

  .el-dialog__header {
    display: none;
  }

  .el-dialog__body {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
    padding: 0;
  }
}

.report-preview-dialog__content {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 12px;
  min-height: 0;
  min-width: 0;
}

.report-preview-dialog__sheet {
  flex: 1;
  min-height: 0;
  width: 100%;
  overflow: hidden;
  border-radius: 8px;
}
</style>
