package com.ym.mec.biz.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.MusicalListDetailDto;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.KitGroupPurchaseTypeEnum;
import com.ym.mec.biz.dal.enums.OrderDetailTypeEnum;
import com.ym.mec.biz.service.MusicGroupPaymentCalenderService;
import com.ym.mec.util.collection.MapUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ym.mec.biz.dal.enums.DealStatusEnum;
import com.ym.mec.biz.service.GoodsService;
import com.ym.mec.biz.service.StudentPaymentOrderDetailService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.service.impl.BaseServiceImpl;

@Service
public class StudentPaymentOrderDetailServiceImpl extends BaseServiceImpl<Long, StudentPaymentOrderDetail> implements StudentPaymentOrderDetailService {

    @Autowired
    private StudentPaymentOrderDetailDao studentPaymentOrderDetailDao;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private TeacherDao teacherDao;
    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private OrganizationDao organizationDao;
    @Autowired
    private MusicGroupPurchaseListDao musicGroupPurchaseListDao;
    @Autowired
    private StudentPaymentOrderDao studentPaymentOrderDao;
    @Autowired
    private StudentRegistrationDao studentRegistrationDao;
    @Autowired
    private SubjectDao subjectDao;
    @Autowired
    private SubjectChangeDao subjectChangeDao;
    @Autowired
    private MusicGroupPaymentCalenderService musicGroupPaymentCalenderService;
    @Autowired
    private MusicGroupPaymentCalenderCourseSettingsDao musicGroupPaymentCalenderCourseSettingsDao;

    @Override
    public BaseDAO<Long, StudentPaymentOrderDetail> getDAO() {
        return studentPaymentOrderDetailDao;
    }

    @Override
    public int batchAdd(List<StudentPaymentOrderDetail> studentPaymentOrderDetailList) {
        return studentPaymentOrderDetailDao.batchAdd(studentPaymentOrderDetailList);
    }

    @Override
    public List<StudentPaymentOrderDetail> findApplyOrderSuccess(String musicGroupId, DealStatusEnum status) {
        return studentPaymentOrderDetailDao.findApplyOrderSuccess(musicGroupId, status);
    }

    @Override
    public List<Goods> getMusicalList(String musicGroupId) {
        List<StudentPaymentOrderDetail> applyOrder = findApplyOrderSuccess(musicGroupId, DealStatusEnum.SUCCESS);
        if (applyOrder == null || applyOrder.size() == 0) {
            return null;
        }
        String goodsIdsStr = "";
        for (StudentPaymentOrderDetail studentPaymentOrderDetail : applyOrder) {
            if (studentPaymentOrderDetail.getGoodsIdList() != null && !studentPaymentOrderDetail.getGoodsIdList().isEmpty()) {
                goodsIdsStr += studentPaymentOrderDetail.getGoodsIdList() + ",";
            }
        }
        if (StringUtils.isBlank(goodsIdsStr)) {
            return null;
        }
        goodsIdsStr = goodsIdsStr.substring(0, goodsIdsStr.length() - 1);

        String[] goodSIdArr = goodsIdsStr.split(",");

        List<Goods> goodies = goodsService.findGoodsByIds(goodsIdsStr);
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        Organization organization = organizationDao.get(musicGroup.getOrganId());
        goodies.forEach(e -> {
            e.setSellCount(0);
            //当作乐团名称字段处理
            e.setMemo(musicGroup.getName());
            //当作分部名称字段处理
            e.setBrief(organization.getName());
            for (String goodsIdStr : goodSIdArr) {
                if (e.getId().equals(Integer.parseInt(goodsIdStr))) {
                    e.setSellCount(e.getSellCount() + 1);
                }
            }
        });
        //乐器更换的
        SubjectChange changeGoods = subjectChangeDao.getChangeGoods(musicGroupId);
        if (changeGoods == null) {
            return goodies;
        }
        String originalGoodsIds = "";
        String changeGoodsIds = "";
        if (StringUtils.isNotBlank(changeGoods.getMusicGroupName())) {
            originalGoodsIds += StringUtils.isNotBlank(originalGoodsIds) ? "," + changeGoods.getMusicGroupName() : changeGoods.getMusicGroupName();
        }
        if (StringUtils.isNotBlank(changeGoods.getOriginalAccessories())) {
            originalGoodsIds += StringUtils.isNotBlank(originalGoodsIds) ? "," + changeGoods.getOriginalAccessories() : changeGoods.getOriginalAccessories();
        }
        if (StringUtils.isNotBlank(changeGoods.getTransNo())) {
            changeGoodsIds += StringUtils.isNotBlank(changeGoodsIds) ? "," + changeGoods.getTransNo() : changeGoods.getTransNo();
        }
        if (StringUtils.isNotBlank(changeGoods.getChangeAccessories())) {
            changeGoodsIds += StringUtils.isNotBlank(changeGoodsIds) ? "," + changeGoods.getChangeAccessories() : changeGoods.getChangeAccessories();
        }
        if (StringUtils.isNotBlank(changeGoodsIds)) {
            String[] changGoodsIdsArr = changeGoodsIds.split(",");
            List<Goods> addGoodies = new ArrayList<>();
            for (String goodsId : changGoodsIdsArr) {
                boolean has = false;
                for (Goods goods : goodies) {
                    if (goodsId.equals(goods.getId().toString())) {
                        goods.setSellCount(goods.getSellCount() + 1);
                        has = true;
                        break;
                    }
                }

                for (Goods addGoods : addGoodies) {
                    if (goodsId.equals(addGoods.getId().toString())) {
                        addGoods.setSellCount(addGoods.getSellCount() + 1);
                        has = true;
                        break;
                    }
                }
                if (!has) {
                    Goods goods = goodsService.get(Integer.parseInt(goodsId));
                    goods.setSellCount(1);
                    goods.setMemo(musicGroup.getName());
                    //当作分部名称字段处理
                    goods.setBrief(organization.getName());
                    addGoodies.add(goods);
                }
            }
            if (addGoodies.size() > 0) {
                goodies.addAll(addGoodies);
            }
        }

        if (StringUtils.isNotBlank(originalGoodsIds)) {
            String[] originalGoodsIdsArr = originalGoodsIds.split(",");
            for (String goodsId : originalGoodsIdsArr) {
                for (Goods goods : goodies) {
                    if (goodsId.equals(goods.getId().toString())) {
                        goods.setSellCount(goods.getSellCount() - 1);
                        break;
                    }
                }
            }
        }
        goodies.removeIf(goods -> goods.getSellCount() <= 0);
        return goodies;
    }

    @Override
    public Boolean verifyMusicalList(String musicGroupId) throws BizException {
        //乐器采购清单是否确认
        Map<String, Object> param = new HashMap<>();
        param.put("musicGroupId", musicGroupId);
        int count = musicGroupPurchaseListDao.queryCount(param);
        if (count > 0) {
            throw new BizException("采购清单已经确认");
        }

        List<Goods> musicalList = getMusicalList(musicGroupId);
        Date date = new Date();
        List<MusicGroupPurchaseList> musicGroupPurchaseLists = new ArrayList<>();
        //发放清单没有时确认特殊处理
        if (musicalList == null || musicalList.size() == 0) {
            musicalList = new ArrayList<>();
            Goods goods = new Goods();
            goods.setId(0);
            goods.setSellCount(0);
            musicalList.add(goods);
        }

        for (Goods goods : musicalList) {
            MusicGroupPurchaseList musicGroupPurchaseList = new MusicGroupPurchaseList();
            musicGroupPurchaseList.setGoodsId(goods.getId());
            musicGroupPurchaseList.setMusicGroupId(musicGroupId);
            musicGroupPurchaseList.setPurchaseNum(goods.getSellCount());
            musicGroupPurchaseList.setCreateTime(date);
            musicGroupPurchaseList.setUpdateTime(date);
            musicGroupPurchaseLists.add(musicGroupPurchaseList);
        }
        musicGroupPurchaseListDao.batchInsert(musicGroupPurchaseLists);
        return true;
    }

    @Override
    public List<Goods> findApplyOrderGoods(Long orderId) {
        List<StudentPaymentOrderDetail> applyOrderGoods = studentPaymentOrderDetailDao.findApplyOrderGoods(orderId);

        if (applyOrderGoods == null || applyOrderGoods.size() == 0) {
            return null;
        }
        String goodsIdsStr = "";
        for (StudentPaymentOrderDetail studentPaymentOrderDetail : applyOrderGoods) {
            if (studentPaymentOrderDetail.getGoodsIdList() != null && !studentPaymentOrderDetail.getGoodsIdList().isEmpty()) {
                goodsIdsStr += studentPaymentOrderDetail.getGoodsIdList() + ",";
            }
        }
        if (goodsIdsStr.isEmpty()) {
            return null;
        }
        goodsIdsStr = goodsIdsStr.substring(0, goodsIdsStr.length() - 1);

        String[] goodSIdArr = goodsIdsStr.split(",");

        List<Goods> goodies = goodsService.findGoodsByIds(goodsIdsStr);

        for (Goods goods : goodies) {
            goods.setSellCount(0);
            for (String goodsIdStr : goodSIdArr) {
                if (goods.getId().equals(Integer.parseInt(goodsIdStr))) {
                    goods.setSellCount(goods.getSellCount() + 1);
                }
            }
        }
        return goodies;
    }

    @Override
    public List<StudentPaymentOrderDetail> findUserApplyOrder(Integer userId, String musicGroupId, DealStatusEnum status) {
        return studentPaymentOrderDetailDao.findUserApplyOrder(userId, musicGroupId, status);
    }

    @Override
    public List<MusicalListDetailDto> getMusicalListDetail(String musicGroupId) {
        List<MusicalListDetailDto> musicalListDetailDtos = studentPaymentOrderDetailDao.getMusicalListDetail(musicGroupId);
        if (musicalListDetailDtos.size() <= 0) {
            return musicalListDetailDtos;
        }
        List<Long> paymentOrderNo = musicalListDetailDtos.stream().map(MusicalListDetailDto::getPaymentOrderId).collect(Collectors.toList());
        List<Integer> userIds = musicalListDetailDtos.stream().map(MusicalListDetailDto::getUserId).collect(Collectors.toList());
        //商品名称
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        Organization organization = organizationDao.get(musicGroup.getOrganId());
        Map<Long, String> goodsNameMap = MapUtil.convertIntegerMap(studentPaymentOrderDetailDao.queryGoodsNames(paymentOrderNo));
        Map<Integer, String> usernameMap = MapUtil.convertIntegerMap(teacherDao.queryUsernameByIds(userIds));
        Map<Long, BigDecimal> expectAmountMap = MapUtil.convertIntegerMap(studentPaymentOrderDao.queryExpectAmount(paymentOrderNo));
        Map<Long, BigDecimal> musicalAmountMap = MapUtil.convertIntegerMap(studentPaymentOrderDetailDao.queryGoodsPrice(paymentOrderNo, "MUSICAL"));
        Map<Long, BigDecimal> accessoriesAmountMap = MapUtil.convertIntegerMap(studentPaymentOrderDetailDao.queryGoodsPrice(paymentOrderNo, "ACCESSORIES"));
        String courseTypes = Arrays.stream(CourseSchedule.CourseScheduleType.values()).map(CourseSchedule.CourseScheduleType::getCode).collect(Collectors.joining(","))+",COURSE";
        Map<Long, BigDecimal> courseAmountMap = MapUtil.convertIntegerMap(studentPaymentOrderDetailDao.queryGoodsPrice(paymentOrderNo, courseTypes));
        Map<Long, String> purchaseTypeMap = MapUtil.convertIntegerMap(studentPaymentOrderDetailDao.queryPurchaseTypeMap(paymentOrderNo));
        Map<Integer, String> userSubjectMap = subjectDao.getRegisterSubject(musicGroupId, userIds).stream().collect(Collectors.toMap(StudentRegistration::getUserId, StudentRegistration::getSubjectName));
        List<StudentPaymentOrderDetail> details = studentPaymentOrderDetailDao.getOrderGoodies(paymentOrderNo);

        musicalListDetailDtos.forEach(e -> {
            e.setGoodsNames(goodsNameMap.get(e.getPaymentOrderId()));
            e.setMusicGroupName(musicGroup.getName());
            e.setUsername(usernameMap.get(e.getUserId()));
            e.setOrganName(organization.getName());
            e.setMusicalAmount(musicalAmountMap.get(e.getPaymentOrderId()));
            e.setAccessoriesAmount(accessoriesAmountMap.get(e.getPaymentOrderId()));
            e.setOrderAmount(expectAmountMap.get(e.getPaymentOrderId()));
            e.setCourseAmount(courseAmountMap.get(e.getPaymentOrderId()));
            e.setSubjectName(userSubjectMap.get(e.getUserId()));
            String s = purchaseTypeMap.get(e.getPaymentOrderId());
            if (StringUtils.isNotEmpty(s)) {
                e.setKitGroupPurchaseTypeEnum(KitGroupPurchaseTypeEnum.valueOf(purchaseTypeMap.get(e.getPaymentOrderId())));
            }
            SubjectChange studentLastChange = subjectChangeDao.getStudentLastChange(e.getUserId(), musicGroupId);
            if(studentLastChange != null){
                studentLastChange.setOriginalKitGroupPurchaseType(studentLastChange.getKitGroupPurchaseType());
            }

            List<Goods> accessories = new ArrayList<>();
            for (StudentPaymentOrderDetail detail : details) {
                if (!e.getPaymentOrderId().equals(detail.getPaymentOrderId())) continue;
                if (detail.getType().equals(OrderDetailTypeEnum.MUSICAL)) {
                    e.setMusicalName(detail.getGoodsList().stream().map(Goods::getName).collect(Collectors.joining(",")));
                } else {
                    accessories.addAll(detail.getGoodsList());
                }
            }
            accessories.sort(Comparator.comparing(Goods::getId));
            e.setAccessoriesName(accessories.stream().map(Goods::getName).collect(Collectors.joining(",")));
        });
        List<SubjectChange> studentGoodies = subjectChangeDao.getStudentGoods(musicGroupId);
        if (studentGoodies.size() <= 0) {
            return musicalListDetailDtos;
        }
        List<SubjectChange> margins = subjectChangeDao.getMargin(musicGroupId);

        for (MusicalListDetailDto musicalListDetailDto : musicalListDetailDtos) {
            for (SubjectChange studentGoods : studentGoodies) {
                if (!musicalListDetailDto.getUserId().equals(studentGoods.getStudentId())) continue;
                musicalListDetailDto.setMusicalName("");
                if (studentGoods.getChangeMusicalGoods() != null) {
                    musicalListDetailDto.setMusicalName(studentGoods.getChangeMusicalGoods().getName());
                }
                musicalListDetailDto.setAccessoriesName("");
                if (studentGoods.getChangeAccessoriesGoods() != null) {
                    List<Goods> changeAccessoriesGoods = studentGoods.getChangeAccessoriesGoods();
                    changeAccessoriesGoods.sort(Comparator.comparing(Goods::getId));
                    String accessoriesNames = changeAccessoriesGoods.stream().map(Goods::getName).collect(Collectors.joining(","));
                    musicalListDetailDto.setAccessoriesName(accessoriesNames);
                }
                musicalListDetailDto.setMusicalAmount(studentGoods.getChangeMusicalPrice());
                musicalListDetailDto.setAccessoriesAmount(studentGoods.getChangeAccessoriesPrice());
                musicalListDetailDto.setKitGroupPurchaseTypeEnum(studentGoods.getKitGroupPurchaseType());
            }
            for (SubjectChange margin : margins) {
                if (!musicalListDetailDto.getUserId().equals(margin.getStudentId())) continue;
                musicalListDetailDto.setOrderAmount(musicalListDetailDto.getOrderAmount().add(margin.getGoodsMargin()));
            }
        }
        return musicalListDetailDtos;
    }

    @Override
    public StudentPaymentOrderDetail findApplyOrderMusical(Long orderId) {
        return studentPaymentOrderDetailDao.findApplyOrderMusical(orderId);
    }

    @Override
    public List<StudentPaymentOrderDetail> getOrderDetail(Long orderId) {
        return studentPaymentOrderDetailDao.getOrderDetail(orderId);
    }

    @Override
    public List<String> getOrderDetailType(Long orderId) {
        return studentPaymentOrderDetailDao.getOrderDetailType(orderId);
    }
}