<script lang="ts" setup>
import type { CreateOrderType, PaymentRowType } from '../types';

import { ref, watch } from 'vue';

import { VbenIcon } from '@vben-core/shadcn-ui';

import { Button, Card, Input, message, Modal, notification } from 'ant-design-vue';
import dayjs from 'dayjs';

import { reconciliateBillsApi } from '#/api/posting/reconciliate';
import { useSysStore } from '#/store';

import Orders from '../components/Orders.vue';
import Selected from '../components/Selected.vue';
import TrainingClass from '../components/TrainingClass.vue';
import VipProduct from '../components/VipProduct.vue';
import WumenCourseProduct from '../components/WumenCourseProduct.vue';
import WumenCourseRecord from '../components/WumenCourseRecord.vue';
import WumenPhysicalProduct from '../components/WumenPhysicalProduct.vue';
import WumenRecharge from '../components/WumenRecharge.vue';
import YiluCourseProduct from '../components/YiluCourseProduct.vue';
import YiluCourseRecord from '../components/YiluCourseRecord.vue';
import YiluPhysicalProduct from '../components/YiluPhysicalProduct.vue';
import YiluRecharge from '../components/YiluRecharge.vue';

const props = withDefaults(
  defineProps<{
    data?: PaymentRowType[];
    show?: boolean;
  }>(),
  {
    show: false,
    data: () => [],
  },
);

const emit = defineEmits(['update:show']);

const needCreateRecord: Record<string, any> = {
  A: WumenCourseRecord,
  B: WumenCourseProduct,
  C: WumenRecharge,
  D: WumenPhysicalProduct,
  E: YiluCourseRecord,
  F: YiluCourseProduct,
  G: YiluRecharge,
  H: YiluPhysicalProduct,
  I: VipProduct,
  J: TrainingClass,
};

const sysStore = useSysStore();

// 批量模式
const isBatchMode = ref(false);

const visible = ref(props.show);
watch(visible, (val) => {
  emit('update:show', val);
});

const multipleCurrentIndex = ref<number[]>([0]);
const multipleCurrentData = ref<PaymentRowType[]>([]);
const selectedAmount = ref();
const pendingData = ref<PaymentRowType[]>([]);

// 监听props.data变化，更新本地pendingData
watch(
  () => props.data,
  (newData) => {
    pendingData.value = newData.toSorted(
      (a, b) => Number(b.orderFlag === 1) - Number(a.orderFlag === 1),
    );
    multipleCurrentIndex.value = [0];
  },
  { immediate: true },
);

function changePendingData(index: number) {
  // 单个模式
  multipleCurrentIndex.value = [index];
  selectedData.value = [];
  selectedRef.value?.clearData();
  selectedAmount.value = null;
  isBatchMode.value = false;
}

function changeBatchSelected() {
  selectedData.value = [];
  selectedRef.value?.clearData();

  if (selectedAmount.value || selectedAmount.value === '0') {
    // 按金额批量选中
    activeTabKey.value = 'B'; // 批量模式不能选订单和记录，默认到课程商品
    isBatchMode.value = true;
    multipleCurrentData.value = pendingData.value.filter(
      (item) => item.fee === Number.parseFloat(selectedAmount.value),
    );
    multipleCurrentIndex.value = multipleCurrentData.value.map((item) =>
      pendingData.value.indexOf(item),
    );
  } else {
    // 取消批量选中
    activeTabKey.value = '0'; // 切换到订单列表
    isBatchMode.value = false;
    changePendingData(0);
  }
}

const tabList = [
  {
    key: '0',
    tab: '订单列表',
  },
  {
    key: 'A',
    tab: '吴门医述开课记录',
  },
  {
    key: 'B',
    tab: '吴门医述课程商品',
  },
  {
    key: 'C',
    tab: '吴门医述充值记录',
  },
  {
    key: 'D',
    tab: '吴门医述实物商品',
  },
  {
    key: 'E',
    tab: '一路健康开课记录',
  },
  {
    key: 'F',
    tab: '一路健康课程商品',
  },
  {
    key: 'G',
    tab: '一路健康充值记录',
  },
  {
    key: 'H',
    tab: '一路健康实物商品',
  },
  {
    key: 'I',
    tab: '开通VIP',
  },
  {
    key: 'J',
    tab: '报名培训班',
  },
];
const activeTabKey = ref('0');
function changeRecordTab(key: string) {
  if (isBatchMode.value && ['0', 'A', 'C', 'E', 'G'].includes(key)) {
    message.warning('批量模式下，不能切换到该选项');
    return;
  }
  activeTabKey.value = key;
}

// 确认对账完成
function onCompleteCheck() {
  notification.success({
    message: '操作成功',
    duration: 1,
  });
  // 删除当前已对账的数据
  const currentIndex = multipleCurrentIndex.value[0] || 0;
  multipleCurrentIndex.value.forEach((index) => {
    pendingData.value.splice(index, 1);
  });

  // 如果没有待对账数据了，关闭弹框
  if (pendingData.value.length === 0) {
    visible.value = false;
    return;
  }

  // 清空待处理账单的已选状态
  multipleCurrentIndex.value = [];
  multipleCurrentData.value = [];
  // 如果当前索引超出了数据范围，重置到第一条，否则下一条（删除已处理索引后，currentIndex即是下一条）
  multipleCurrentIndex.value[0] = Math.min(currentIndex, pendingData.value.length - 1);
}
// 其他方式--确认对账 --------------
// 已选列表
const selectedRef = ref();
const errorData = ref<CreateOrderType[]>([]);
const selectedData = ref<CreateOrderType[]>([]);
const needCreateRecordRef = ref();
// 选中
function onSelectRecord(rows: CreateOrderType[]) {
  const addData = rows.filter(
    (item) => !selectedData.value.some((selected) => selected.id === item.id),
  );
  selectedData.value.push(...addData);
  selectedRef.value?.handleAdd(addData);
}
// 取消选中
function onDeleteChecked(ids: number[]) {
  ids.forEach((id) => {
    const rowData = selectedData.value.find((item) => item.id === id);
    const index = selectedData.value.findIndex((item) => item.id === id);
    if (index !== -1) {
      selectedData.value.splice(index, 1);
      selectedRef.value?.deleteData(id);
    }
    if (rowData && needCreateRecordRef.value) {
      needCreateRecordRef.value.cancelCheck(id);
    }
  });
}

function completeSubmitCheck(item: CreateOrderType) {
  if (!item.realMoney) {
    message.error(`《${item.productName}》请填写实际金额`);
    return true;
  }
  if (!item.orderMoney) {
    message.error(`《${item.productName}》请填写订单金额`);
    return true;
  }
  // 单个模式必须填手机号
  if (!isBatchMode.value && !item.tel) {
    message.error(`《${item.productName}》请填写手机号`);
    return true;
  }
  // 单个模式课程、vip必须填开始时间和结束时间
  if (!isBatchMode.value && (item.orderType === '1' || item.orderType === '2') && !item.startTime) {
    message.error(`《${item.productName}》请填写开始时间`);
    return true;
  }
  if (!isBatchMode.value && (item.orderType === '1' || item.orderType === '2') && !item.endTime) {
    message.error(`《${item.productName}》请填写到期时间`);
    return true;
  }
  // 批量模式课程、vip必须填到期时间
  if (isBatchMode.value && (item.orderType === '1' || item.orderType === '2') && !item.endTime) {
    message.error(`《${item.productName}》请填写到期时间`);
    return true;
  }

  return false;
}
// 确认对账
async function onCompleteCheckCreated() {
  if (multipleCurrentIndex.value.length === 0) {
    message.error('请选择账单');
    return;
  }
  if (selectedData.value.length === 0) {
    message.error('请选择对账数据');
  }

  const selected = selectedRef.value.getData();

  // 检查已选数据中是否有未填写的表单项
  const emptyItem = selected.find((item: CreateOrderType) => {
    return completeSubmitCheck(item);
  });
  if (emptyItem) {
    errorData.value = [emptyItem];
    return;
  } else {
    errorData.value = [];
  }

  // 验证订单金额不能小于实际金额
  const invalidItem = selected.find((item: CreateOrderType) => {
    return Number.parseFloat(item.orderMoney) < Number.parseFloat(item.realMoney);
  });
  if (invalidItem) {
    errorData.value = [invalidItem];
    message.error(`《${invalidItem.productName}》订单金额不能小于实际金额`);
    return;
  } else {
    errorData.value = [];
  }

  // 判断已选的数据填写的实际金额总和是否与对账单金额一致
  const totalRealMoney = selected.reduce(
    (acc: number, item: CreateOrderType) => acc + Number.parseFloat(item.realMoney),
    0,
  );
  if (totalRealMoney !== pendingData.value?.[multipleCurrentIndex.value[0] ?? 0]?.fee) {
    message.error('已选数据填写的实际金额总和与对账单金额不一致');
    return;
  }

  const data = selected.map((item: CreateOrderType) => {
    const result: any = {
      ...item,
      districtMoney: (
        Number.parseFloat(item.orderMoney) - Number.parseFloat(item.realMoney)
      ).toString(),
    };

    // 单选模式且只有VIP和课程订单才处理开始时间和结束时间
    if (!isBatchMode.value && (item.orderType === '1' || item.orderType === '2')) {
      result.startTime = dayjs(item.startTime).format('YYYY-MM-DD'); // 格式化开始时间
      result.endTime = dayjs(item.startTime)
        .add(Number.parseFloat(item.endTime), 'day')
        .format('YYYY-MM-DD'); // 处理结束时间，根据传入的vb时间和课程时长计算
    }

    // 如果是多选模式，处理相应数据
    if (isBatchMode.value) {
      delete result.paymentId;
      result.startTime = '';
    }

    return result;
  });

  const paymentIds = multipleCurrentData.value.map((item) => item.id);
  // 调用接口
  await (isBatchMode.value
    ? reconciliateBillsApi.manualCheckCreatedBatch({
        paymentIds: paymentIds.join(','),
        orders: data,
      })
    : reconciliateBillsApi.manualCheckCreated(data));
  onCompleteCheck();
  // 清空已选列表
  selectedData.value = [];
  selectedRef.value?.clearData();
}
</script>

<template>
  <Modal
    v-model:open="visible"
    width="100%"
    title="人工对账"
    :footer="null"
    centered
    wrap-class-name="full-modal"
  >
    <div class="flex gap-2">
      <Card title="待对账列表" class="w-1/4" size="small">
        <div class="flex items-center justify-between p-1 pb-2">
          <Input
            v-model:value="selectedAmount"
            addon-before="批量选中金额"
            allow-clear
            class="w-60"
            @change="changeBatchSelected"
          />
          <div class="ml-2">已选中：{{ multipleCurrentIndex.length }}</div>
        </div>
        <div class="flex flex-col gap-2 overflow-y-auto px-1" style="height: calc(100vh - 170px)">
          <div
            v-for="(item, index) in pendingData"
            :key="item.id"
            :class="{ active: multipleCurrentIndex.includes(index) }"
            class="pay-order-item relative"
            @click="changePendingData(index)"
          >
            <div>关联sn号：{{ item.relationSn }}</div>
            <div>业务流水号：{{ item.transactionSn }}</div>
            <div>财务流水号：{{ item.financeSn }}</div>
            <div>金额：{{ item.fee }}</div>
            <div>支付方式：{{ sysStore.getDictMap('payment', item.type) }}</div>
            <div>时间：{{ dayjs(item.ctime).format('YYYY-MM-DD HH:mm:ss') }}</div>

            <VbenIcon
              v-if="item.orderFlag === 1"
              icon="ant-design:star-fill"
              class="absolute right-1 top-1 h-5 w-5 text-red-500"
            />
          </div>
        </div>
      </Card>
      <div class="flex w-3/4 flex-1 flex-col gap-2">
        <Card
          :tab-list="tabList"
          disabled
          :active-tab-key="activeTabKey"
          @tab-change="changeRecordTab"
          class="order-card flex-1"
          size="small"
        >
          <Orders
            v-if="activeTabKey === '0'"
            :payment-id="pendingData[multipleCurrentIndex[0] ?? 0]?.id"
            @complete-check="onCompleteCheck"
          />
          <component
            :is="needCreateRecord[activeTabKey]"
            v-if="activeTabKey !== '0'"
            ref="needCreateRecordRef"
            :tab-key="activeTabKey"
            :payment="pendingData[multipleCurrentIndex[0] ?? 0]"
            :selected-data="selectedData"
            @complete-check="onSelectRecord"
            @deleted-checked="onDeleteChecked"
          />
        </Card>
        <Card
          v-if="activeTabKey !== '0'"
          :title="`已选列表(${selectedData.length})`"
          class="h-[270px] w-full"
          size="small"
        >
          <template #extra>
            <Button type="primary" size="small" @click="onCompleteCheckCreated()">确认对账</Button>
          </template>
          <Selected
            ref="selectedRef"
            :error-item="errorData"
            :is-batch-mode="isBatchMode"
            @deleted-checked="onDeleteChecked"
          />
        </Card>
      </div>
    </div>
  </Modal>
</template>

<style lang="scss" scoped>
.pay-order-item {
  padding: 10px;
  border: 1px solid #d9d9d9;
  border-radius: 10px;

  &.active {
    padding: 9px;
    border: 2px solid #1890ff;
    background-color: rgba(24, 144, 255, 0.05);
  }
}
:deep(.ant-card-body) {
  padding: 5px !important;
  padding-bottom: 10px !important;
}
.order-card {
  width: 100%;
  :deep(.ant-card-body) {
    padding: 1px !important;
    height: calc(100% - 41px); // 减去标签页头部高度
    // background-color: #f1f3f6;
  }
}
</style>
