package com.xjrsoft.module.student.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xjrsoft.common.page.ConventPage;
import com.xjrsoft.common.utils.VoToColumnUtil;
import com.xjrsoft.module.base.entity.BaseClass;
import com.xjrsoft.module.base.entity.BaseSemester;
import com.xjrsoft.module.student.dto.BaseStudentInfoDetailDto;
import com.xjrsoft.module.student.dto.PbVXsxxsfytbExcelDto;
import com.xjrsoft.module.student.dto.PbVXsxxsfytbPageDto;
import com.xjrsoft.module.student.dto.PersonalPortraitFeeInformationDto;
import com.xjrsoft.module.student.entity.BaseStudent;
import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll;
import com.xjrsoft.module.student.entity.PbSemesterConfig;
import com.xjrsoft.module.student.entity.PbVXsxxsfytb;
import com.xjrsoft.module.student.mapper.PbSemesterConfigMapper;
import com.xjrsoft.module.student.mapper.PbVXsxxsfytbMapper;
import com.xjrsoft.module.student.service.IPbVXsxxsfytbService;
import com.xjrsoft.module.student.vo.BaseClassQfCountVo;
import com.xjrsoft.module.student.vo.FeeDetailListVo;
import com.xjrsoft.module.student.vo.PbVXsxxsfytbExcelVo;
import com.xjrsoft.module.student.vo.PbVXsxxsfytbFeeitemVo;
import com.xjrsoft.module.student.vo.PbVXsxxsfytbPageVo;
import com.xjrsoft.module.student.vo.PbVXsxxsfytbPersonal;
import com.xjrsoft.module.student.vo.PbVXsxxsfytbPersonalMap;
import com.xjrsoft.module.student.vo.PersonalPortraitFeeInformationVo;
import com.xjrsoft.module.teacher.entity.XjrUser;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @title:
* @Author dzx
* @Date: 2024-03-13
* @Version 1.0
*/
@Service
@AllArgsConstructor
public class PbVXsxxsfytbServiceImpl extends MPJBaseServiceImpl<PbVXsxxsfytbMapper, PbVXsxxsfytb> implements IPbVXsxxsfytbService {

    private final PbVXsxxsfytbMapper pbVXsxxsfytbMapper;
    private final PbSemesterConfigMapper pbSemesterConfigMapper;

    @Override
    public PersonalPortraitFeeInformationVo listCostInformation(PersonalPortraitFeeInformationDto dto) {

        //查出所有的消费记录
        MPJLambdaWrapper<PbVXsxxsfytb> pbVXsxxsfytbMPJLambdaWrapper = new MPJLambdaWrapper<>();
        pbVXsxxsfytbMPJLambdaWrapper
                .selectAs(BaseSemester::getId, PbVXsxxsfytbPersonal::getBaseSemester)
                .selectAs(BaseSemester::getName, PbVXsxxsfytbPersonal::getBaseSemesterCn)
                .select(PbVXsxxsfytb.class, x -> VoToColumnUtil.fieldsToColumns(PbVXsxxsfytbPersonal.class).contains(x.getProperty()))
                .leftJoin(XjrUser.class, XjrUser::getCredentialNumber, PbVXsxxsfytb::getPersonalid)
                .leftJoin(PbSemesterConfig.class, PbSemesterConfig::getBeltcode, PbVXsxxsfytb::getBeltcode)
                .leftJoin(BaseSemester.class, BaseSemester::getId, PbSemesterConfig::getBaseSemesterId)
                .eq(dto.getUserId() != null && dto.getUserId() > 0, XjrUser::getId, dto.getUserId())
                .like(dto.getYear() != null && !dto.getYear().equals(""),PbVXsxxsfytb::getBeltcode, dto.getYear())
                ;
        List<PbVXsxxsfytbPersonal> pbVXsxxsfytbPersonalList = this.selectJoinList(PbVXsxxsfytbPersonal.class, pbVXsxxsfytbMPJLambdaWrapper);

        // 统计总消费金额
        BigDecimal totalConsumption = pbVXsxxsfytbPersonalList.stream()
                .map(p -> p.getFactrecarmny().add((p.getArrearagemny()==null?BigDecimal.ZERO:p.getArrearagemny())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 按学期分组并处理数据
        List<PbVXsxxsfytbPersonalMap> pbVXsxxsfytbPersonalMapList = pbVXsxxsfytbPersonalList.stream()
                .collect(Collectors.groupingBy(PbVXsxxsfytbPersonal::getBaseSemester))
                .entrySet().stream()
                .map(entry -> {
                    String baseSemester = entry.getKey();
                    List<PbVXsxxsfytbPersonal> pbVXsxxsfytbPersonals = entry.getValue();

                    // 合并相同缴费项目
                    Map<String, PbVXsxxsfytbPersonal> pbVXsxxsfytbPersonalByItemMap = pbVXsxxsfytbPersonals.stream()
                            .collect(Collectors.toMap(PbVXsxxsfytbPersonal::getFeeitemcode, p -> p, (existing, replacement) -> {
                                existing.setFactar(existing.getFactar().add(replacement.getFactar()));
                                existing.setFactrecarmny(existing.getFactrecarmny().add(replacement.getFactrecarmny()));
                                existing.setAdjustmny(existing.getAdjustmny().add(replacement.getAdjustmny()));
                                existing.setArrearagemny(existing.getArrearagemny().add(replacement.getArrearagemny()));
                                return existing;
                            }));

                    // 构建PbVXsxxsfytbPersonalMap对象
                    PbVXsxxsfytbPersonalMap pbVXsxxsfytbPersonalMap = new PbVXsxxsfytbPersonalMap();
                    pbVXsxxsfytbPersonalMap.setBaseSemester(baseSemester);
                    pbVXsxxsfytbPersonalMap.setBaseSemesterCn(pbVXsxxsfytbPersonals.get(0).getBaseSemesterCn());
                    pbVXsxxsfytbPersonalMap.setPbVXsxxsfytbPersonalList(new ArrayList<>(pbVXsxxsfytbPersonalByItemMap.values()));

                    return pbVXsxxsfytbPersonalMap;
                })
                .collect(Collectors.toList());

        // 构建返回对象
        PersonalPortraitFeeInformationVo personalPortraitFeeInformationVo = new PersonalPortraitFeeInformationVo();
        personalPortraitFeeInformationVo.setTotalConsumption(totalConsumption);
        personalPortraitFeeInformationVo.setPbVXsxxsfytbPersonalMapList(pbVXsxxsfytbPersonalMapList);

        return personalPortraitFeeInformationVo;
    }

    @Override
    public IPage<PbVXsxxsfytbPageVo> getPage(PbVXsxxsfytbPageDto dto) {
        if(dto.getClassIds() != null && !dto.getClassIds().equals("")){
            String[] strArray = dto.getClassIds().split(",");
            List<String> strList = Arrays.asList(strArray);
            dto.setClassIdList(strList);
        }

        MPJLambdaWrapper<PbVXsxxsfytb> pbVXsxxsfytbMPJLambdaWrapper = new MPJLambdaWrapper<>();
        if (dto.getSemesterId() != null && dto.getSemesterId() > 0) {
            pbVXsxxsfytbMPJLambdaWrapper.exists("select 1 from `pb_semester_config` where base_semester_id = " + dto.getSemesterId() + " and beltcode = t.beltcode");
        }

        pbVXsxxsfytbMPJLambdaWrapper
                .disableSubLogicDel()
                .like(dto.getFeeitemname() != null && !dto.getFeeitemname().equals(""), PbVXsxxsfytb::getFeeitemname, dto.getFeeitemname())
                .like(dto.getName() != null && !dto.getName().equals(""), PbVXsxxsfytb::getFeeobjname, dto.getName())
                .eq(dto.getStudentId() != null && !dto.getStudentId().equals(""), BaseStudent::getStudentId, dto.getStudentId())
                .in(dto.getClassIdList() != null && !dto.getClassIdList().isEmpty(), BaseStudentSchoolRoll::getClassId, dto.getClassIdList())
                .eq(dto.getSemesterId() != null && dto.getSemesterId() > 0, PbSemesterConfig::getBaseSemesterId, dto.getSemesterId())
                .like(dto.getJfzt() != null && !"".equals(dto.getJfzt()), PbVXsxxsfytb::getJfzt, dto.getJfzt())
                .leftJoin(XjrUser.class, XjrUser::getCredentialNumber, PbVXsxxsfytb::getPersonalid)
                .leftJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, XjrUser::getId)
                .leftJoin(BaseClass.class, BaseClass::getId, BaseStudentSchoolRoll::getClassId)
                .leftJoin(BaseStudent.class, BaseStudent::getUserId, XjrUser::getId)
                .leftJoin(PbSemesterConfig.class, PbSemesterConfig::getBeltcode, PbVXsxxsfytb::getBeltcode)
                .leftJoin(BaseSemester.class, BaseSemester::getId, PbSemesterConfig::getBaseSemesterId)
                .leftJoin("xjr_user x1 on x1.id = t3.teacher_id")
                .select("x1.name as teacher_name")
                .selectAs(BaseSemester::getId, PbVXsxxsfytbPageVo::getBaseSemester)
                .selectAs(XjrUser::getId, PbVXsxxsfytbPageVo::getUserId)
                .selectAs(BaseClass::getName, PbVXsxxsfytbPageVo::getClassname)
                .selectAs(BaseSemester::getName, PbVXsxxsfytbPageVo::getBaseSemesterCn)
                .select(PbVXsxxsfytb.class, x -> VoToColumnUtil.fieldsToColumns(PbVXsxxsfytbPageVo.class).contains(x.getProperty()))
                ;
        if(StrUtil.isNotEmpty(dto.getField()) && StrUtil.isNotEmpty(dto.getOrder())){
            if("ascend".equals(dto.getOrder())){
                if("baseSemesterCn".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByAsc(BaseSemester::getName);
                }else if("feeobjname".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByAsc(PbVXsxxsfytb::getFeeobjname);
                }else if("personalid".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByAsc(PbVXsxxsfytb::getPersonalid);
                }else if("sex".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByAsc(PbVXsxxsfytb::getSex);
                }else if("feeitemname".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByAsc(PbVXsxxsfytb::getFeeitemname);
                }else if("factar".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByAsc(PbVXsxxsfytb::getFactar);
                }else if("ktje".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByDesc(PbVXsxxsfytb::getQfje);
                }else if("refundmny".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByAsc(PbVXsxxsfytb::getRefundmny);
                }else if("qfje".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByDesc(PbVXsxxsfytb::getQfje);
                }else if("factrecarmny".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByAsc(PbVXsxxsfytb::getFactrecarmny);
                }
            }else if("descend".equals(dto.getOrder())){
                if("baseSemesterCn".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByDesc(BaseSemester::getName);
                }else if("feeobjname".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByDesc(PbVXsxxsfytb::getFeeobjname);
                }else if("personalid".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByDesc(PbVXsxxsfytb::getPersonalid);
                }else if("sex".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByDesc(PbVXsxxsfytb::getSex);
                }else if("feeitemname".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByDesc(PbVXsxxsfytb::getFeeitemname);
                }else if("factar".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByDesc(PbVXsxxsfytb::getFactar);
                }else if("ktje".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByAsc(PbVXsxxsfytb::getQfje);
                }else if("refundmny".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByDesc(PbVXsxxsfytb::getRefundmny);
                }else if("qfje".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByAsc(PbVXsxxsfytb::getQfje);
                }else if("factrecarmny".equals(dto.getField())){
                    pbVXsxxsfytbMPJLambdaWrapper.orderByDesc(PbVXsxxsfytb::getFactrecarmny);
                }
            }
        }
        return this.selectJoinListPage(ConventPage.getPageCustomOrder(dto), PbVXsxxsfytbPageVo.class, pbVXsxxsfytbMPJLambdaWrapper);
    }

    @Override
    public List<PbVXsxxsfytbExcelVo> getList(PbVXsxxsfytbExcelDto dto) {
        MPJLambdaWrapper<PbVXsxxsfytb> pbVXsxxsfytbMPJLambdaWrapper = new MPJLambdaWrapper<>();

        pbVXsxxsfytbMPJLambdaWrapper
                .disableSubLogicDel()
                .in(dto.getPksfxxytbs() != null && !dto.getPksfxxytbs().isEmpty(), PbVXsxxsfytb::getPksfxxytb, dto.getPksfxxytbs())
                .leftJoin(XjrUser.class, XjrUser::getCredentialNumber, PbVXsxxsfytb::getPersonalid)
                .leftJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, XjrUser::getId)
                .leftJoin(PbSemesterConfig.class, PbSemesterConfig::getBeltcode, PbVXsxxsfytb::getBeltcode)
                .leftJoin(BaseSemester.class, BaseSemester::getId, PbSemesterConfig::getBaseSemesterId)
                .leftJoin(BaseClass.class, BaseClass::getId, BaseStudentSchoolRoll::getClassId)
                .selectAs(BaseClass::getName, PbVXsxxsfytbExcelVo::getClassname)
                .selectAs(BaseSemester::getId, PbVXsxxsfytbExcelVo::getBaseSemester)
                .selectAs(XjrUser::getId, PbVXsxxsfytbExcelVo::getUserId)
                .selectAs(BaseSemester::getName, PbVXsxxsfytbExcelVo::getBaseSemesterCn)
                .select(PbVXsxxsfytb.class, x -> VoToColumnUtil.fieldsToColumns(PbVXsxxsfytbExcelVo.class).contains(x.getProperty()))
        ;
        List<PbVXsxxsfytbExcelVo> list = this.selectJoinList(PbVXsxxsfytbExcelVo.class, pbVXsxxsfytbMPJLambdaWrapper);
        for (PbVXsxxsfytbExcelVo pbVXsxxsfytbExcelVo : list) {
            if(pbVXsxxsfytbExcelVo.getQfje().compareTo(BigDecimal.ZERO) > 0){//正数
                pbVXsxxsfytbExcelVo.setQfje(pbVXsxxsfytbExcelVo.getQfje().abs());
                pbVXsxxsfytbExcelVo.setKtje(BigDecimal.ZERO);
            }else if(pbVXsxxsfytbExcelVo.getQfje().compareTo(BigDecimal.ZERO) < 0){
                pbVXsxxsfytbExcelVo.setKtje(pbVXsxxsfytbExcelVo.getQfje().abs());
                pbVXsxxsfytbExcelVo.setQfje(BigDecimal.ZERO);
            }
        }
        return list;
    }

    @Override
    public List<BaseClassQfCountVo> getClassQfCount() {
        return pbVXsxxsfytbMapper.getClassQfCount();
    }

    /**
     * 查询学生最新一学期的费用情况
     * @param credentialNumber
     * @return
     */
    @Override
    public PbVXsxxsfytbFeeitemVo getStudentFeeInfo(String credentialNumber) {
        BaseStudentInfoDetailDto dto = new BaseStudentInfoDetailDto();
        dto.setCredentialNumber(credentialNumber);
        String lastBeltcode = pbSemesterConfigMapper.getLastBeltcode();
        dto.setBeltcode(lastBeltcode);
        return pbVXsxxsfytbMapper.getStudentFeeInfo(dto);
    }

    @Override
    public List<FeeDetailListVo> getFeeDetail(String studentcode) {
        return pbVXsxxsfytbMapper.getFeeDetail(studentcode);
    }

    @Override
    public Long getIsArrears(String credentialNumber) {
        Long l = pbVXsxxsfytbMapper.selectCount(
                new QueryWrapper<PbVXsxxsfytb>().lambda()
                        .eq(PbVXsxxsfytb::getStudentcode, credentialNumber)
                        .ge(PbVXsxxsfytb::getQfje, 0)
        );
        if(l > 1){
            l = 1L;
        }
        return l;
    }
}
