package com.yida.data.mall.service.impl;

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.Dict;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.constant.StringConstant;
import com.yida.data.common.core.entity.mall.EduBill;
import com.yida.data.common.core.entity.mall.EduBillOrder;
import com.yida.data.common.core.entity.mall.EduBillStudent;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.enums.OrderStatusEnum;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.common.core.utils.FebsUtil;
import com.yida.data.mall.dto.BillStudentSelectPageDTO;
import com.yida.data.mall.dto.BillUserSaveDTO;
import com.yida.data.mall.mapper.EduBillMapper;
import com.yida.data.mall.mapper.EduBillStudentMapper;
import com.yida.data.mall.service.EduBillOrderItemService;
import com.yida.data.mall.service.EduBillOrderService;
import com.yida.data.mall.service.EduBillService;
import com.yida.data.mall.service.EduBillStudentService;
import com.yida.data.mall.vo.BillItemInfoVO;
import com.yida.data.mall.vo.BillStudentInfoVO;
import com.yida.data.mall.vo.h5.H5BillItemVO;
import com.yida.data.system.feign.RemoteCommonService;
import com.yida.data.user.feign.RemoteStudentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 缴费单缴费学生 Service实现
 *
 * @author ZYJ
 * @date 2021-12-30
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduBillStudentServiceImpl extends ServiceImpl
        <EduBillStudentMapper, EduBillStudent> implements EduBillStudentService {

    private final RemoteStudentService remoteStudentService;
    private final RemoteCommonService remoteCommonService;

    private final EduBillOrderService eduBillOrderService;
    private final EduBillOrderItemService eduBillOrderItemService;

    @Lazy
    @Resource
    private EduBillService eduBillService;

    private final EduBillMapper eduBillMapper;

    private final RedisService redisService;

    @Override
    public IPage<BillStudentInfoVO> listBillUserPage(BillStudentSelectPageDTO dto) {
        // 查询学生信息
        EduStudent eduStudent = new EduStudent();
        BeanUtils.copyProperties(dto, eduStudent);
        eduStudent.setSchoolId(FebsUtil.getDeptId());
        List<EduStudent> studentList = remoteStudentService.listBaseStudent(eduStudent).getData();

        Page<BillStudentInfoVO> page = Page.of(dto.getPageNum(), dto.getPageSize());
        if (CollUtil.isNotEmpty(studentList)) {
            // 学生分组
            Map<Long, List<EduStudent>> studentMap = studentList.stream().collect(Collectors.groupingBy(EduStudent::getId));
            // 查询账单人员列表
            page.setRecords(baseMapper.listBillUserPage(page, dto, studentList));

            EduBill bill = eduBillMapper.selectById(dto.getBillId());
            page.getRecords().forEach(billStudentInfoVO -> {
                // 匹配学生信息
                EduStudent student = studentMap.get(billStudentInfoVO.getStudentId()).get(0);
                BeanUtils.copyProperties(student, billStudentInfoVO);
                // 判断是否禁用
                boolean disabled = !(Objects.isNull(bill.getBillStartDate()) || bill.getBillStartDate().isAfter(LocalDateTime.now()));
                billStudentInfoVO.setDisabled(disabled);
                // 判断缴费金额
                billStudentInfoVO.setPayMoney(eduBillOrderService.sumPayOrderPrice(dto.getBillId(), billStudentInfoVO.getStudentId()));
            });
        } else {
            page = new Page<>();
        }
        return page;
    }

    @Override
    public List<BillStudentInfoVO> listBillUser(Long billId) {
        // 查询学生信息
        EduStudent eduStudent = new EduStudent();
        eduStudent.setSchoolId(FebsUtil.getDeptId());
        List<EduStudent> studentList = remoteStudentService.listBaseStudent(eduStudent).getData();
        if (CollUtil.isNotEmpty(studentList)) {
            // 学生分组
            Map<Long, List<EduStudent>> studentMap = studentList.stream().collect(Collectors.groupingBy(EduStudent::getId));
            // 查询账单人员列表
            List<BillStudentInfoVO> list = baseMapper.listBillUserPage(null,
                    BillStudentSelectPageDTO.builder()
                            .billId(billId)
                            .build(),
                    studentList);
            list.forEach(billStudentInfoVO -> {
                // 匹配学生信息
                EduStudent student = studentMap.get(billStudentInfoVO.getStudentId()).get(0);
                BeanUtils.copyProperties(student, billStudentInfoVO);
                // 判断是否禁用
                billStudentInfoVO.setDisabled(true);
            });
            return list;
        } else {
            return new ArrayList<>();
        }
    }

    @Override
    public void saveBillUser(BillUserSaveDTO billUserSaveDTO) {
        billUserSaveDTO.getAchieveList().forEach(dto -> {
            EduBillStudent eduBillStudent = new EduBillStudent();
            BeanUtils.copyProperties(dto, eduBillStudent);
            eduBillStudent.setBillId(billUserSaveDTO.getBillId());
            this.save(eduBillStudent);
        });
    }

    @Override
    public void deleteBillUser(Long billStudentId, Long studentId, Long billId) {
        // 判断是否有缴费
        BigDecimal payPrice = eduBillOrderService.sumPayOrderPrice(billId, studentId);
        if (Objects.nonNull(payPrice)) {
            throw new FebsException("当前学生已经缴费过，无法删除！");
        }
        // 判断是否有未关闭订单
        long count = eduBillOrderService.count(Wrappers.lambdaQuery(new EduBillOrder())
                .eq(EduBillOrder::getBillId, billId)
                .eq(EduBillOrder::getStudentId, studentId)
                .eq(EduBillOrder::getOrderStatus, OrderStatusEnum.NOT_PAY.getStatus())
        );
        if (count > 0) {
            throw new FebsException("当前学生有未关闭的订单，暂时无法删除！");
        }
        this.removeById(billStudentId);
    }

    @Override
    public IPage<Map<String, String>> listBillPayDetailPage(BillStudentSelectPageDTO dto) {

        // 查询学生信息
        EduStudent eduStudent = new EduStudent();
        BeanUtils.copyProperties(dto, eduStudent);
        eduStudent.setSchoolId(FebsUtil.getDeptId());
        List<EduStudent> studentList = remoteStudentService.listBaseStudent(eduStudent).getData();

        if (CollUtil.isNotEmpty(studentList)) {
            Page<BillStudentInfoVO> page = Page.of(dto.getPageNum(), dto.getPageSize());
            // 学生分组
            Map<Long, List<EduStudent>> studentMap = studentList.stream().collect(Collectors.groupingBy(EduStudent::getId));
            // 查询账单人员列表
            List<BillStudentInfoVO> list = baseMapper.listBillUserPage(page, dto, studentList);

            // 实际返回的分页数据
            Page<Map<String, String>> returnPage = new Page<>();
            BeanUtils.copyProperties(page, returnPage);

            List<Map<String, String>> returnList = new ArrayList<>();
            // 查询缴费信息
            list.forEach(billStudentInfoVO -> {
                // 匹配学生信息
                EduStudent student = studentMap.get(billStudentInfoVO.getStudentId()).get(0);
                BeanUtils.copyProperties(student, billStudentInfoVO);

                Map<String, String> map = JSONObject.parseObject(JSONObject.toJSONString(billStudentInfoVO), new TypeReference<Map<String, String>>() {
                });
                // 查询总金额
                map.put("payMoney", String.valueOf(eduBillOrderService.sumPayOrderPrice(dto.getBillId(), student.getId())));
                // 查询学生缴费信息
                List<H5BillItemVO> payInfo = eduBillOrderItemService.getPayInfo(dto.getBillId(), student.getId());
                payInfo.forEach(item -> {
                    String itemPayName = "i" + item.getItemId() + item.getItemName();
                    if (CollUtil.isNotEmpty(item.getSubItemList())) {
                        item.getSubItemList().forEach(subItem -> {
                            // 选项拼接方式为 i+项目id+项目名称+s+选项id+选项名称
                            map.put(itemPayName + "s" + subItem.getSubItemId() + subItem.getSubItemName(),
                                    NumberUtil.sub(subItem.getSubItemPrice(), item.getReductionPrice()).toString());
                        });
                    } else {
                        // 项目拼接方式为 i+项目id+项目名称
                        map.put(itemPayName, NumberUtil.sub(item.getItemPrice(), item.getReductionPrice()).toString());
                    }
                });

                returnList.add(map);
            });
            returnPage.setRecords(returnList);
            return returnPage;
        } else {
            return new Page<>();
        }
    }

//    @Override
//    public void exportBillPayData(BillStudentSelectPageDTO dto, HttpServletResponse response) {
//        try {
//            // 查询学生信息
//            EduStudent eduStudent = new EduStudent();
//            BeanUtils.copyProperties(dto, eduStudent);
//            eduStudent.setSchoolId(FebsUtil.getDeptId());
//            List<EduStudent> studentList = remoteStudentService.listBaseStudent(eduStudent).getData();
//
//            // 导出人员列表数据
//            List<List<String>> exportDataList = new ArrayList<>();
//
//            if (CollUtil.isNotEmpty(studentList)) {
//                // 学生分组
//                Map<Long, List<EduStudent>> studentMap = studentList.stream().collect(Collectors.groupingBy(EduStudent::getId));
//                // 查询账单人员列表
//                List<BillStudentInfoVO> list = baseMapper.listBillUserPage(null, dto, studentList);
//                // 查询家庭类型
//                List<Dict> familyTypeList = remoteCommonService.getDict(DictType.FAMILY_TYPE.getValue()).getData();
//
//                list.forEach(billStudentInfoVO -> {
//                    // 匹配学生信息
//                    EduStudent student = studentMap.get(billStudentInfoVO.getStudentId()).get(0);
//                    // 查询学生具体缴费金额
//                    List<BillPayVO> payList = eduBillOrderItemService.listItemPayInfo(dto.getBillId(), student.getId());
//
//                    List<String> price = payList.stream().map(billPayVO -> {
//                        BillPayPriceVO billPayPriceVO = billPayVO.getBillPayPriceVO();
//                        if (Objects.isNull(billPayPriceVO) || Objects.isNull(billPayPriceVO.getItemPrice())) {
//                            return "—";
//                        }
//                        BigDecimal returnPrice = NumberUtil.sub(billPayPriceVO.getItemPrice(), billPayPriceVO.getReductionPrice());
//                        return Objects.isNull(returnPrice) ? "—" : returnPrice.toString();
//                    }).collect(Collectors.toList());
//                    // 查询总金额数据
//                    BigDecimal payOrderPrice = eduBillOrderService.sumPayOrderPrice(dto.getBillId(), student.getId());
//                    // 封装每一行数据
//                    ArrayList<String> singleList = CollUtil.newArrayList(student.getStuName(), student.getGradeName(),
//                            student.getClassName(), student.getStuNumber(),
//                            handelStudentType(student.getType()),
//                            handleFamilyType(student.getFamilyType(), familyTypeList));
//                    singleList.addAll(price);
//                    singleList.add(Objects.isNull(payOrderPrice) ? "—" : payOrderPrice.toString());
//                    // 添加excel数据
//                    exportDataList.add(singleList);
//                });
//            }
//            // 导出数据
//            EasyExcel.write(response.getOutputStream())
//                    .excelType(ExcelTypeEnum.XLS)
//                    // 这里放入动态头
//                    .head(getExportHead(dto.getBillId())).sheet("缴费明细")
//                    // 当然这里数据也可以用 List<List<String>> 去传入
//                    .doWrite(exportDataList);
//        } catch (Exception e) {
//            log.error("导出缴费明细数据错误", e);
//            throw new FebsException("导出缴费明细数据错误");
//        }
//    }

    @Override
    public String exportBillPayData(BillStudentSelectPageDTO dto, HttpServletResponse response) {
        return (String) redisService.get(CachePrefixConstant.BILL_PAY_DETAIL_EXPORT_URL + dto.getBillId());
    }

    /**
     * 生成缴费账单动态表头数据
     *
     * @param billId 账单id
     * @return java.util.List<java.util.List < java.lang.String>>
     * @author ZYJ
     * @date 2022/4/19 16:06
     */
    private List<List<String>> getExportHead(Long billId) {
        // 表头list的生成，实际的表头信息可以从数据库或者缓存等处动态读取
        List<List<String>> allColList = new ArrayList<>();
        // 姓名表头
        allColList.add(CollUtil.newArrayList("姓名"));
        // 年级表头
        allColList.add(CollUtil.newArrayList("年级"));
        // 班级表头
        allColList.add(CollUtil.newArrayList("班级"));
        // 学号表头
        allColList.add(CollUtil.newArrayList("学号"));
        // 学生类型表头
        allColList.add(CollUtil.newArrayList("学生类型"));
        // 家庭类型表头
        allColList.add(CollUtil.newArrayList("家庭类型"));

        // 项目动态表头
        List<BillItemInfoVO> colList = eduBillService.listBillPayDetailTableCol(billId);
        colList.forEach(item -> {
            if (CollUtil.isNotEmpty(item.getSubItemList())) {
                item.getSubItemList().forEach(subItem -> allColList.add(CollUtil.newArrayList("缴费项目", item.getItemName(), subItem.getSubItemName())));
            } else {
                allColList.add(CollUtil.newArrayList("缴费项目", item.getItemName()));
            }
        });
        // 总金额表头
        allColList.add(CollUtil.newArrayList("总金额"));
        return allColList;
    }

    /**
     * 转换学生类别
     *
     * @param studentType 学生类别，0-走读，1-住宿
     * @return java.lang.String
     * @author ZYJ
     * @date 2022/4/19 16:19
     */
    private String handelStudentType(Integer studentType) {
        if (Objects.nonNull(studentType)) {
            return studentType.equals(0) ? "走读" : "住宿";
        } else {
            return "";
        }
    }

    /**
     * 转换家庭类型
     *
     * @param familyType     学生家庭类型
     * @param familyTypeList 家庭类型字典
     * @return java.lang.String
     * @author ZYJ
     * @date 2022/4/19 16:21
     */
    private String handleFamilyType(String familyType, List<Dict> familyTypeList) {
        if (StringUtils.isNotBlank(familyType)) {
            List<String> list = new ArrayList<>();
            for (Dict dict : familyTypeList) {
                if (familyType.contains(dict.getValue())) {
                    list.add(dict.getLabel());
                }
            }
            return String.join(StringConstant.COMMA, list);
        } else {
            return "";
        }
    }
}
