package com.zksy.property.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zksy.property.domain.AReceiptInfo;
import com.zksy.property.domain.vo.AReceiptInfoVo;
import com.zksy.property.mapper.AReceiptInfoMapper;
import com.zksy.property.service.AReceiptInfoService;
import com.zksy.service.MinioFileStorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author Administrator
* @description 针对表【a_receipt_info(收据信息表)】的数据库操作Service实现
* @createDate 2025-07-29 15:30:56
*/
@Service
public class AReceiptInfoServiceImpl extends ServiceImpl<AReceiptInfoMapper, AReceiptInfo>
    implements AReceiptInfoService{

    @Autowired
    private AReceiptInfoMapper areceiptInfoMapper;

    @Override
    public Page<AReceiptInfo> findByPage(long pageNum, long pageSize, String receiptNumber, String payer, String paymentMethod, String generationDate) {
        Page<AReceiptInfo> page = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<AReceiptInfo> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.like(receiptNumber != null,AReceiptInfo::getReceiptNumber,receiptNumber);
        queryWrapper.like(payer != null,AReceiptInfo::getPayer,payer);
        queryWrapper.like(paymentMethod != null,AReceiptInfo::getPaymentMethod,paymentMethod);
        queryWrapper.like(generationDate != null,AReceiptInfo::getGenerationDate,generationDate);
        Page<AReceiptInfo> page1 = this.page(page, queryWrapper);
        return page1;
    }

    @Override
    public List<AReceiptInfo> getAReceiptInfoList(String receiptNumber, String payer, String paymentMethod, String generationDate) {
        LambdaQueryWrapper<AReceiptInfo> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.like(receiptNumber != null,AReceiptInfo::getReceiptNumber,receiptNumber);
        queryWrapper.like(payer != null,AReceiptInfo::getPayer,payer);
        queryWrapper.like(paymentMethod != null,AReceiptInfo::getPaymentMethod,paymentMethod);
        queryWrapper.like(generationDate != null,AReceiptInfo::getGenerationDate,generationDate);
        List<AReceiptInfo> list = this.list(queryWrapper);
        return list;
    }

    @Autowired
    private MinioFileStorageService minioFileStorageService;

    @Override
    @Transactional
    public boolean removeBatchByIdsWithUrl(List<String> ids) {
        List<AReceiptInfo> aReceiptInfoList = listByIds(ids);
        List<String> list = aReceiptInfoList.stream().map(AReceiptInfo::getAttachmentUrl).collect(Collectors.toList());
        minioFileStorageService.deleteFileBatch(list);
        return removeBatchByIds(ids);
    }

    @Override
    public Page<AReceiptInfoVo> findByPageWithContract(long pageNum, long pageSize, String receiptNumber, String payer, String paymentMethod, String contractNumber) {
        Page<AReceiptInfoVo> page = new Page<>(pageNum, pageSize);
        return areceiptInfoMapper.selectReceiptWithContractByPage(page, receiptNumber, payer, paymentMethod, contractNumber);
    }

    @Override
    public Map<String, BigDecimal> calculateMonthlyStatistics(int year) {
        List<AReceiptInfo> receiptList = list(new QueryWrapper<AReceiptInfo>()
                .ge("accounting_date", LocalDate.of(year, 1, 1))
                .le("accounting_date", LocalDate.of(year, 12, 31)));

        Map<String, BigDecimal> monthlyData = new LinkedHashMap<>();
        for (int month = 1; month <= 12; month++) {
            monthlyData.put(String.format("%d-%02d", year, month), BigDecimal.ZERO);
        }

        // 统计数据
        for (AReceiptInfo receipt : receiptList) {
            if (receipt.getAccountingDate() != null && receipt.getTotalAmount() != null) {
                String monthKey = String.format("%d-%02d",
                        year,
                        receipt.getAccountingDate().getMonthValue()
                );
                monthlyData.merge(monthKey, receipt.getTotalAmount(), BigDecimal::add);
            }
        }

        return monthlyData;
    }

    @Override
    public Map<String, BigDecimal> calculateQuarterlyStatistics(int year) {
        List<AReceiptInfo> receiptList = list(new QueryWrapper<AReceiptInfo>()
                .ge("accounting_date", LocalDate.of(year, 1, 1))
                .le("accounting_date", LocalDate.of(year, 12, 31)));

        Map<String, BigDecimal> quarterlyData = new TreeMap<>();
        for (int quarter = 1; quarter <= 4; quarter++) {
            quarterlyData.put(year + "Q" + quarter, BigDecimal.ZERO);
        }

        for (AReceiptInfo receipt : receiptList) {
            LocalDate date = receipt.getAccountingDate();
            if (date != null && receipt.getTotalAmount() != null) {
                int quarter = (date.getMonthValue() - 1) / 3 + 1;
                String quarterKey = year + "Q" + quarter;
                quarterlyData.merge(quarterKey, receipt.getTotalAmount(), BigDecimal::add);
            }
        }

        return quarterlyData;
    }

    @Override
    public Map<String, BigDecimal> calculateYearlyStatistics() {
        List<AReceiptInfo> receiptList = list();
        Map<String, BigDecimal> yearlyData = new TreeMap<>();

        for (AReceiptInfo receipt : receiptList) {
            LocalDate date = receipt.getAccountingDate();
            if (date != null && receipt.getTotalAmount() != null) {
                String yearKey = String.valueOf(date.getYear());
                yearlyData.merge(yearKey, receipt.getTotalAmount(), BigDecimal::add);
            }
        }

        return yearlyData;
    }

    @Override
    public List<Integer> getExistingYears() {
        List<AReceiptInfo> receiptList = list();

        return receiptList.stream()
                .map(AReceiptInfo::getAccountingDate)
                .filter(Objects::nonNull)
                .map(date -> date.getYear())
                .distinct()
                .sorted()
                .collect(Collectors.toList());
    }
}




