<script lang="ts" setup>
import type { Dayjs } from 'dayjs';

import { ref, watch } from 'vue';

import { debounce } from 'lodash-es';

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

import dayjs from 'dayjs';

import {
  Button,
  Checkbox,
  DatePicker,
  message,
  Select,
  Space,
} from 'ant-design-vue';

import { downloadByData } from '#/util/tool';

import {
  exportReconciliationExcelApi,
  getReconciliationDrugOptions,
  getReconciliationOrderOptions,
} from '#/views/finance/reconciliation/api';

import { loadPageSearchTimeRange } from '#/views/finance/reconciliation/utils/formCache';

import { getStoreOption } from '#/views/system/store/api';

defineOptions({
  name: 'ReconciliationExportModal',
});

type SelectLabeled = { value: number; label: string };

const storeId = ref<number | undefined>(undefined);

const storeLabel = ref('');

const searchTime = ref<[Dayjs, Dayjs]>([dayjs().startOf('month'), dayjs()]);

const storeOptions = ref<{ label: string; value: number }[]>([]);

const loading = ref(false);

const fetchingStores = ref(false);

const drugSelect = ref<SelectLabeled | undefined>(undefined);
const orderSelect = ref<SelectLabeled | undefined>(undefined);
const drugSelectOptions = ref<SelectLabeled[]>([]);
const orderSelectOptions = ref<SelectLabeled[]>([]);
const byOrder = ref(false);

/** 诊所账号：仅允许导出本店，隐藏诊所选择 */
const storeExportLocked = ref(false);

function searchTimeRange(): [string, string] {
  return [searchTime.value[0].format('YYYY-MM-DD'), searchTime.value[1].format('YYYY-MM-DD')];
}

const searchDrugOptions = debounce(async (raw: string) => {
  if (!storeId.value) {
    drugSelectOptions.value = [];
    return;
  }
  try {
    const res = await getReconciliationDrugOptions({
      q: raw,
      store_id: storeId.value,
      search_time: searchTimeRange(),
    });
    drugSelectOptions.value = (res.items || []).map((i) => ({ label: i.label, value: i.value }));
  } catch {
    drugSelectOptions.value = [];
  }
}, 300);

const searchOrderOptions = debounce(async (raw: string) => {
  if (!storeId.value) {
    orderSelectOptions.value = [];
    return;
  }
  try {
    const res = await getReconciliationOrderOptions({
      q: raw,
      store_id: storeId.value,
      search_time: searchTimeRange(),
    });
    orderSelectOptions.value = (res.items || []).map((i) => ({ label: i.label, value: i.value }));
  } catch {
    orderSelectOptions.value = [];
  }
}, 300);

watch(storeId, (id) => {
  if (storeExportLocked.value) {
    return;
  }
  const o = storeOptions.value.find((x) => x.value === id);
  storeLabel.value = o?.label ?? '';
  orderSelect.value = undefined;
  orderSelectOptions.value = [];
});

const loadStores = () => {
  fetchingStores.value = true;
  getStoreOption({})
    .then((res: any[]) => {
      storeOptions.value = (res || []).map((item: any) => ({
        label: item.name,
        value: item.id,
      }));
    })
    .finally(() => {
      fetchingStores.value = false;
    });
};

function popupContainerBody() {
  return document.body;
}

const [Modal, modalApi] = useVbenModal({
  fullscreenButton: false,
  draggable: true,
  onCancel() {
    modalApi.close();
  },
  onConfirm: async () => {
    if (!storeId.value) {
      message.warning('请选择诊所');
      return;
    }
    if (!searchTime.value?.[0] || !searchTime.value?.[1]) {
      message.warning('请选择时间范围');
      return;
    }
    loading.value = true;
    try {
      const res = await exportReconciliationExcelApi({
        store_id: storeId.value,
        search_time: searchTime.value,
        drug_id: drugSelect.value?.value,
        order_id: orderSelect.value?.value,
        by_order: byOrder.value ? 1 : 0,
      });
      const end = searchTime.value[1].format('YYYY-MM-DD');
      const safeName = (storeLabel.value || '诊所').replace(/[\\/:*?"<>|]+/g, '_');
      downloadByData(res.data, `${safeName}_${end}.xlsx`);
      message.success('导出成功');
      modalApi.close();
    } catch (e: any) {
      message.error(e?.message || '导出失败');
    } finally {
      loading.value = false;
    }
  },
  onOpenChange(isOpen: boolean) {
    if (isOpen) {
      const data =
        modalApi.getData<{
          search_time?: [Dayjs, Dayjs];
          store_export_locked?: boolean;
          locked_store_id?: number;
          locked_store_name?: string;
          drug_select?: SelectLabeled;
          order_select?: SelectLabeled;
          by_order?: boolean;
        }>() || {};
      if (data.search_time?.[0] && data.search_time?.[1]) {
        searchTime.value = [dayjs(data.search_time[0]), dayjs(data.search_time[1])];
      } else {
        const r = loadPageSearchTimeRange();
        searchTime.value = [r[0], r[1]];
      }
      drugSelect.value = data.drug_select;
      orderSelect.value = data.order_select;
      byOrder.value = !!data.by_order;
      drugSelectOptions.value = [];
      orderSelectOptions.value = [];

      storeExportLocked.value = !!data.store_export_locked;
      if (storeExportLocked.value && data.locked_store_id != null) {
        storeId.value = data.locked_store_id;
        storeLabel.value = data.locked_store_name || '本诊所';
      } else {
        storeId.value = undefined;
        storeLabel.value = '';
        loadStores();
      }
    }
  },
});
</script>

<template>
  <Modal class="w-[560px]" title="导出对账 Excel">
    <div class="flex flex-col gap-4 py-2">
      <div v-if="!storeExportLocked">
        <div class="mb-1 text-sm text-muted-foreground">诊所</div>
        <Select
          v-model:value="storeId"
          show-search
          :filter-option="
            (input: string, option: any) =>
              (option?.label ?? '').toLowerCase().includes(input.toLowerCase())
          "
          :options="storeOptions"
          :loading="fetchingStores"
          allow-clear
          placeholder="请选择诊所"
          class="w-full"
          option-filter-prop="label"
        />
      </div>
      <div v-else>
        <div class="mb-1 text-sm text-muted-foreground">诊所</div>
        <div class="rounded border px-3 py-2 text-sm">
          {{ storeLabel || '本诊所' }}（ID: {{ storeId }}）
        </div>
      </div>
      <div>
        <div class="mb-1 text-sm text-muted-foreground">时间范围</div>
        <DatePicker.RangePicker
          v-model:value="searchTime"
          class="w-full"
          format="YYYY-MM-DD"
          :get-popup-container="popupContainerBody"
        />
      </div>
      <div>
        <Checkbox v-model:checked="byOrder">按订单维度导出（药品 sheet 与列表勾选一致）</Checkbox>
      </div>
      <div>
        <div class="mb-1 text-sm text-muted-foreground">药品（可选）</div>
        <Select
          v-model:value="drugSelect"
          label-in-value
          :filter-option="false"
          show-search
          allow-clear
          :disabled="!storeId"
          placeholder="先选诊所后搜索"
          :options="drugSelectOptions"
          class="w-full"
          @search="searchDrugOptions"
        />
      </div>
      <div>
        <div class="mb-1 text-sm text-muted-foreground">订单（可选）</div>
        <Select
          v-model:value="orderSelect"
          label-in-value
          :filter-option="false"
          show-search
          allow-clear
          :disabled="!storeId"
          placeholder="先选诊所后搜索"
          :options="orderSelectOptions"
          class="w-full"
          @search="searchOrderOptions"
        />
      </div>
      <Space v-if="!storeExportLocked">
        <Button @click="loadStores()">刷新诊所列表</Button>
      </Space>
    </div>
  </Modal>
</template>
