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

import type {
  IncomeItem,
  NoNeedAmortizateMonthStatistics,
  SumAndNoNeedAmortizateMonthDataItem,
  SumMonthStatistics,
} from './types';

import { computed, onMounted, reactive, ref } from 'vue';

import { Loading, Page } from '@vben/common-ui';
import { downloadFileFromBlobPart } from '@vben/utils';

import { Button, Card, DatePicker, message } from 'ant-design-vue';
import dayjs from 'dayjs';

import { statisticsApi } from '#/api/statistics';
import { useSysStore } from '#/store/sys';

import {
  handleSumAndNoNeedAmortizateMonthData,
  handleTianyibiDetailData,
  handleVipAndCourseMonthData,
} from './report-utils';

const sysStore = useSysStore();
const loading = ref(false);
const date = ref(dayjs().format('YYYY-MM'));
const disabledDate = (date: Dayjs) => {
  const currentYear = dayjs().year();
  const currentMonth = dayjs().month();

  // 如果是当前年份，超过本月的月份不能选
  if (date.year() === currentYear) {
    return date.month() > currentMonth;
  }

  // 如果是未来年份，所有月份都不能选
  if (date.year() > currentYear) {
    return true;
  }

  // 过去年份的所有月份都可以选
  return false;
};

const platList = computed(() => sysStore.getDictList('payment'));
const loadingText = '数据加载中...';
const loadingError = '数据加载或解析失败';

// 获取收款汇总数据和实物和培训班数据
const sumAndNoNeedAmortizateMonthData = reactive({
  paymentSummary: [] as SumMonthStatistics[],
  physicalAndTraining: [] as NoNeedAmortizateMonthStatistics[],
});
async function getSumAndNoNeedAmortizateMonth() {
  const res = await statisticsApi.getSumMonthStatistics(date.value);
  sumAndNoNeedAmortizateMonthData.paymentSummary = res.paymentSummary || [];
  sumAndNoNeedAmortizateMonthData.physicalAndTraining = res.physicalAndTraining || [];
}

// 处理收款汇总数据
const sumMonthLoading = ref<boolean | string>(loadingText);
const sumMonthData = ref<SumAndNoNeedAmortizateMonthDataItem[]>([]);
const sumMonthTotal = ref(0);

function handleSumMonthData() {
  sumMonthData.value = [];
  sumMonthTotal.value = 0;
  try {
    const paymentSummary = sumAndNoNeedAmortizateMonthData.paymentSummary;
    const { sumMonthTotal: sumMonthTotalValue, resultData: sumMonthDataValue } =
      handleSumAndNoNeedAmortizateMonthData(paymentSummary, {
        childDictArr: [
          { title: '实物', type: 'shiwu' },
          { title: '培训班', type: 'peixun' },
          { title: '课程', type: 'kecheng' },
          { title: 'vip', type: 'vip' },
          { title: '天医币', type: 'tianyibi' },
        ],
        typeDictArr: platList.value.map((item) => item.label),
        typeKey: 'plat',
      });
    sumMonthData.value = sumMonthDataValue;
    sumMonthTotal.value = sumMonthTotalValue;

    sumMonthLoading.value = false;
  } catch {
    message.error('收款汇总数据解析失败');
    sumMonthLoading.value = loadingError;
  }
}

// 处理实物和培训班数据
const noNeedAmortizateMonthLoading = ref<boolean | string>(loadingText);
const noNeedAmortizateMonthData = ref<SumAndNoNeedAmortizateMonthDataItem[]>([]);
const noNeedAmortizateMonthTotal = ref(0);
const noNeedAmortizateList = ['实物', '培训班'];

function handleNoNeedAmortizateMonthData() {
  noNeedAmortizateMonthData.value = [];
  noNeedAmortizateMonthTotal.value = 0;
  try {
    const physicalAndTraining = sumAndNoNeedAmortizateMonthData.physicalAndTraining;
    const { sumMonthTotal: sumMonthTotalValue, resultData: sumMonthDataValue } =
      handleSumAndNoNeedAmortizateMonthData(physicalAndTraining, {
        childDictArr: [
          { title: '微信', type: 'wx' },
          { title: '银行', type: 'bank' },
          { title: '支付宝', type: 'zfb' },
          { title: '天医币', type: 'tianyibi' },
        ],
        typeDictArr: noNeedAmortizateList,
        typeKey: 'type',
      });
    noNeedAmortizateMonthData.value = sumMonthDataValue;
    noNeedAmortizateMonthTotal.value = sumMonthTotalValue;

    noNeedAmortizateMonthLoading.value = false;
  } catch {
    message.error('实物和培训班数据解析失败');
    noNeedAmortizateMonthLoading.value = loadingError;
  }
}

async function querySumAndNoNeedAmortizateMonthData() {
  sumMonthLoading.value = loadingText;
  noNeedAmortizateMonthLoading.value = loadingText;
  await getSumAndNoNeedAmortizateMonth();
  handleSumMonthData();
  handleNoNeedAmortizateMonthData();
}

// 查询和处理VIP数据
const vipMonthLoading = ref<boolean | string>(loadingText);
const vipMonthData = ref({
  incomes: [] as IncomeItem[],
  incomesTotal: 0,
  notyet: 0,
  already: 0,
  now: 0,
  lastNotyet: 0,
});

// 获取VIP数据
async function queryVipMonthData() {
  vipMonthLoading.value = loadingText;
  try {
    const incomeTypes = platList.value.map((item) => item.label);
    incomeTypes.push('天医币');
    const res = await handleVipAndCourseMonthData(
      statisticsApi.getVipStatistics,
      date.value,
      incomeTypes,
    );
    vipMonthData.value = res;
    vipMonthLoading.value = false;
  } catch {
    message.error('VIP收入和摊销数据解析失败');
    vipMonthLoading.value = loadingError;
  }
}

// 查询和处理课程数据
const courseMonthLoading = ref<boolean | string>(loadingText);
const courseMonthData = ref({
  incomes: [] as IncomeItem[],
  incomesTotal: 0,
  notyet: 0,
  already: 0,
  now: 0,
  lastNotyet: 0,
});

// 获取课程数据
async function queryCourseMonthData() {
  courseMonthLoading.value = loadingText;
  try {
    const incomeTypes = platList.value.map((item) => item.label);
    incomeTypes.push('天医币');
    const res = await handleVipAndCourseMonthData(
      statisticsApi.getCourseStatistics,
      date.value,
      incomeTypes,
    );
    courseMonthData.value = res;
    courseMonthLoading.value = false;
  } catch {
    message.error('课程收入数据解析失败');
    courseMonthLoading.value = loadingError;
  }
}

// 处理天医币明细数据
const tianyibiMonthLoading = ref<boolean | string>(loadingText);
const tianyibiMonthData = ref({
  incomes: [] as IncomeItem[],
  consumes: [] as IncomeItem[],
  incomesTotal: 0,
  consumesTotal: 0,
  surplus: 0,
  lastSurplus: 0,
});

// 获取天医币明细数据
async function queryTianyibiMonthData() {
  tianyibiMonthLoading.value = loadingText;
  try {
    const res = await handleTianyibiDetailData(
      statisticsApi.getReportTianyibi,
      date.value,
      platList.value.map((item) => item.label),
      ['培训班', '课程', 'vip', '实物'],
    );
    tianyibiMonthData.value = res;
    tianyibiMonthLoading.value = false;
  } catch {
    message.error('天医币明细数据解析失败');
    tianyibiMonthLoading.value = loadingError;
  }
}

// 查询方法
async function query() {
  loading.value = true;
  await Promise.all([
    querySumAndNoNeedAmortizateMonthData(),
    queryVipMonthData(),
    queryCourseMonthData(),
    queryTianyibiMonthData(),
  ]);
  loading.value = false;
}

// 组件挂载时查询数据
onMounted(() => {
  query();
});

// 下载月总结报表
const downloadMonthStatisticsLoading = ref(false);
async function downloadMonthStatistics() {
  downloadMonthStatisticsLoading.value = true;
  const [year = '', month = ''] = date.value.split('-');
  const Blob = await statisticsApi.downloadSumMonthStatistics({
    month,
    year,
  });
  downloadFileFromBlobPart({
    source: Blob,
    fileName: `${year}年${month}月财务报表.xlsx`,
  });
  downloadMonthStatisticsLoading.value = false;
}
</script>

<template>
  <Page auto-content-height>
    <Loading class="flex h-full flex-col rounded-md bg-white" :spinning="loading">
      <div class="search-form p-4">
        <DatePicker
          v-model:value="date"
          picker="month"
          :disabled-date="disabledDate"
          value-format="YYYY-MM"
          @change="query"
        />
        <Button type="primary" class="ml-2" @click="query">查询</Button>
      </div>
      <div class="h-2 bg-gray-100"></div>
      <div class="content relative min-h-2 flex-1 px-3 py-4">
        <div class="max-h-full w-full overflow-auto px-1">
          <Card :bordered="false" class="h-full !shadow-none">
            <template #title>
              <div class="flex items-center justify-between">
                <div
                  class="absolute left-0 top-0 flex h-full items-center justify-center bg-[#1890FF] pl-5 pr-8 text-lg font-bold text-white"
                  style="clip-path: polygon(0 0, 100% 0, 90% 100%, 0 100%)"
                >
                  {{ dayjs(date).format('YYYY年M月') }} 财务报表
                </div>
                <div class="absolute bottom-0 right-0 h-1 w-full bg-[#1890FF]"></div>
              </div>
            </template>
            <template #extra>
              <Button
                :loading="downloadMonthStatisticsLoading"
                type="link"
                size="large"
                class="!px-0"
                @click="downloadMonthStatistics"
              >
                下载报表
              </Button>
            </template>
            <div class="grid grid-cols-4 gap-3">
              <!-- 收款汇总 -->
              <div class="col-span-1 row-span-2">
                <Card
                  class="h-full"
                  title="收款汇总"
                  size="small"
                  :head-style="{
                    backgroundColor: '#1890FF',
                    color: '#fff',
                    borderColor: '#1890FF',
                  }"
                >
                  <template #extra>
                    <span v-if="!sumMonthLoading"> 合计：{{ sumMonthTotal }}元 </span>
                  </template>
                  <div v-if="sumMonthLoading" class="flex h-full items-center justify-center">
                    {{ sumMonthLoading }}
                  </div>
                  <div v-else>
                    <div v-for="item in sumMonthData" :key="item.type">
                      <div class="font-bold">{{ `${item.type}(合计：${item.sumFee}元)` }}</div>
                      <div
                        v-for="child in item.children"
                        :key="child.title"
                        class="flex h-full items-center"
                      >
                        <div>{{ `${child.title}：${child.fee}元` }}</div>
                      </div>
                    </div>
                  </div>
                </Card>
              </div>

              <!-- 天医币明细 -->
              <div class="col-span-1 row-span-2">
                <Card
                  class="h-full"
                  title="天医币明细"
                  size="small"
                  :head-style="{
                    backgroundColor: '#1890FF',
                    color: '#fff',
                    borderColor: '#1890FF',
                  }"
                >
                  <div v-if="tianyibiMonthLoading" class="flex h-full items-center justify-center">
                    {{ tianyibiMonthLoading }}
                  </div>
                  <div v-else>
                    <div class="font-bold">
                      上月天医币剩余 {{ tianyibiMonthData.lastSurplus }}元
                    </div>
                    <div class="font-bold">进项 合计{{ tianyibiMonthData.incomesTotal }}元</div>
                    <div
                      v-for="child in tianyibiMonthData.incomes"
                      :key="child.type"
                      class="flex items-center"
                    >
                      {{
                        `${child.type}：${child.fee}元${child.point !== child.fee ? `(${child.point}天医币)` : ''}`
                      }}
                    </div>
                    <div class="font-bold">出项 合计{{ tianyibiMonthData.consumesTotal }}元</div>
                    <div
                      v-for="child in tianyibiMonthData.consumes"
                      :key="child.type"
                      class="flex items-center"
                    >
                      {{ `${child.type}：${child.fee}元` }}
                    </div>
                    <div class="font-bold">APP用户天医币剩余 {{ tianyibiMonthData.surplus }}元</div>
                  </div>
                </Card>
              </div>

              <!--  -->
              <div class="col-span-2">
                <Card
                  class="h-full"
                  title="实物和培训班收入"
                  size="small"
                  :head-style="{
                    backgroundColor: '#1890FF',
                    color: '#fff',
                    borderColor: '#1890FF',
                  }"
                >
                  <div
                    v-if="noNeedAmortizateMonthLoading"
                    class="flex h-full items-center justify-center"
                  >
                    {{ noNeedAmortizateMonthLoading }}
                  </div>
                  <div v-else>
                    <div v-for="item in noNeedAmortizateMonthData" :key="item.type">
                      <div class="font-bold">{{ `${item.type}` }}</div>
                      <div class="grid grid-cols-3">
                        <div
                          v-for="child in item.children"
                          :key="child.title"
                          class="flex items-center"
                        >
                          {{ `${child.title}：${child.fee}元` }}
                        </div>
                        <div class="flex items-center">
                          {{ `合计：${item.sumFee}元` }}
                        </div>
                      </div>
                    </div>
                  </div>
                </Card>
              </div>

              <!-- VIP收入及摊销 -->
              <div class="col-span-1">
                <Card
                  class="h-full"
                  title="VIP收入及摊销"
                  size="small"
                  :head-style="{
                    backgroundColor: '#1890FF',
                    color: '#fff',
                    borderColor: '#1890FF',
                  }"
                >
                  <div v-if="vipMonthLoading" class="flex h-full items-center justify-center">
                    {{ vipMonthLoading }}
                  </div>
                  <div v-else>
                    <div class="font-bold">上月剩余摊销 {{ vipMonthData.lastNotyet }}元</div>
                    <div class="font-bold">收入 合计{{ vipMonthData.incomesTotal }}元</div>
                    <div
                      v-for="child in vipMonthData.incomes"
                      :key="child.type"
                      class="flex items-center"
                    >
                      {{ `${child.type}：${child.fee}元` }}
                    </div>
                    <div class="font-bold">月摊销 {{ vipMonthData.now }}元</div>
                    <div class="font-bold">已摊销 {{ vipMonthData.already }}元</div>
                    <div class="font-bold">剩余摊销 {{ vipMonthData.notyet }}元</div>
                  </div>
                </Card>
              </div>
              <!-- 课程收入及摊销 -->
              <div class="col-span-1">
                <Card
                  class="h-full"
                  title="课程收入及摊销"
                  size="small"
                  :head-style="{
                    backgroundColor: '#1890FF',
                    color: '#fff',
                    borderColor: '#1890FF',
                  }"
                >
                  <div v-if="courseMonthLoading" class="flex h-full items-center justify-center">
                    {{ courseMonthLoading }}
                  </div>
                  <div v-else>
                    <div class="font-bold">上月剩余摊销 {{ courseMonthData.lastNotyet }}元</div>
                    <div class="font-bold">收入 合计{{ courseMonthData.incomesTotal }}元</div>
                    <div
                      v-for="child in courseMonthData.incomes"
                      :key="child.type"
                      class="flex items-center"
                    >
                      {{ `${child.type}：${child.fee}元` }}
                    </div>
                    <div class="font-bold">月摊销 {{ courseMonthData.now }}元</div>
                    <div class="font-bold">已摊销 {{ courseMonthData.already }}元</div>
                    <div class="font-bold">剩余摊销 {{ courseMonthData.notyet }}元</div>
                  </div>
                </Card>
              </div>
            </div>
            <div class="mt-2 flex justify-end gap-10 bg-gray-50 p-2 text-black">
              <span>
                经合计计算后剩余天医币：
                {{
                  tianyibiMonthLoading
                    ? '等待计算'
                    : `${Number.parseFloat(
                        (
                          tianyibiMonthData.lastSurplus +
                          tianyibiMonthData.incomesTotal -
                          tianyibiMonthData.consumesTotal
                        ).toFixed(3),
                      )}元`
                }}
              </span>
              <span>
                经合计计算后VIP剩余摊销：
                {{
                  vipMonthLoading
                    ? '等待计算'
                    : `${Number.parseFloat(
                        (
                          vipMonthData.lastNotyet +
                          vipMonthData.incomesTotal -
                          vipMonthData.now
                        ).toFixed(3),
                      )}元`
                }}
              </span>
              <span>
                经合计计算后课程剩余摊销：
                {{
                  courseMonthLoading
                    ? '等待计算'
                    : `${Number.parseFloat(
                        (
                          courseMonthData.lastNotyet +
                          courseMonthData.incomesTotal -
                          courseMonthData.now
                        ).toFixed(3),
                      )}元`
                }}
              </span>
            </div>
          </Card>
        </div>
      </div>
    </Loading>
  </Page>
</template>

<style scoped>
:deep(.ant-card-head) {
  position: relative;
}
</style>
