package com.kcim.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kcim.common.constants.NumberConstant;
import com.kcim.common.exception.CostException;
import com.kcim.common.util.BeanUtil;
import com.kcim.common.util.UserContext;
import com.kcim.dao.mapper.AccountingMapper;
import com.kcim.dao.mapper.AccountingProductMapper;
import com.kcim.dao.mapper.ProductMapper;
import com.kcim.dao.model.Accounting;
import com.kcim.dao.model.AccountingProduct;
import com.kcim.dao.model.Product;
import com.kcim.dao.model.dto.AccountProductSaveDTO;
import com.kcim.dao.repository.AccountingProductRepository;
import com.kcim.dao.repository.AccountingRepository;
import com.kcim.vo.AccountProductVO;
import com.kcim.vo.ProductMapVO;
import com.kcim.vo.ProductVO;
import com.kcim.service.AccountingProductService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

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


@Service("accountingProductService")
@Slf4j
@AllArgsConstructor
public class AccountingProductServiceImpl extends ServiceImpl<AccountingProductMapper, AccountingProduct> implements AccountingProductService {

    private final AccountingMapper accountingMapper;

    private final ProductMapper productMapper;

   private final AccountingRepository accountingRepository;

    private final AccountingProductRepository accountingProductRepository;
    /**
     * 列表
     *
     * @param accountType
     * @return
     */
    @Override
    public List<AccountProductVO> selectList(Integer accountType) {
        return select(accountType);
//        Long hospId = UserContext.getCurrentLoginHospId();
//        List<Accounting> list = accountingMapper.selectList(
//                new LambdaQueryWrapper<Accounting>()
//                        .eq(Accounting::getHospId, hospId)
//                        .eq(Accounting::getAccountingType, accountType)
//                        .orderByDesc(Accounting::getCreateTime)
//        );
//
//        if (CollUtil.isEmpty(list)) {
//            return Collections.emptyList();
//        }
//        List<AccountProductVO> accountProductVOS = BeanUtil.convertList(list, AccountProductVO.class);
//        // 所有的
//        List<AccountProductVO> all = new ArrayList<>();
//        for (AccountProductVO accountProductVO : accountProductVOS) {
//            AccountProductVO productVO = BeanUtil.convertObj(accountProductVO, AccountProductVO.class);
//            all.add(productVO);
//        }
//        // 顶层的
//        List<AccountProductVO> parents = all.stream().filter(i -> i.getParentId() == 0).collect(Collectors.toList());
//        List<AccountProductVO> accountVOS = new ArrayList<>();
//        for (AccountProductVO parent : parents) {
//            List<AccountProductVO> accountTree = this.getAccountTree(parent, all);
//            accountVOS.addAll(accountTree);
//        }
//        return accountVOS;
    }


    public List<AccountProductVO> select(Integer accountType){
        //查找会计科目
        List<Accounting> list = accountingRepository.getList(accountType);
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        List<AccountProductVO> accountProductVOS = BeanUtil.convertList(list, AccountProductVO.class);
        List<Long> collect = accountProductVOS.stream().map(AccountProductVO::getId).collect(Collectors.toList());
        List<ProductMapVO> productMap = accountingProductRepository.getProductMap(collect);
        if(!CollectionUtils.isEmpty(productMap)){
            Map<Long, List<ProductMapVO>> collect1 = productMap.stream().collect(Collectors.groupingBy(ProductMapVO::getAccountingId));
            for (AccountProductVO accountProductVO : accountProductVOS) {
                List<ProductMapVO> productMapVOS = collect1.get(accountProductVO.getId());
                if(!CollectionUtils.isEmpty(productMapVOS)){
                    List<ProductVO> productVOS = BeanUtil.convertList(productMapVOS, ProductVO.class);
                    accountProductVO.setProductVOs(productVOS);
                }
            }
        }
        Map<Long, List<AccountProductVO>> parentGroup = accountProductVOS.stream().collect(Collectors.groupingBy(AccountProductVO::getParentId));
        List<AccountProductVO> parent = parentGroup.get(NumberConstant.ZERO_L);
        parentGroup.remove(NumberConstant.ZERO_L);
        for (AccountProductVO vo : parent) {
            if (!CollectionUtils.isEmpty(parentGroup.get(vo.getId()))) {
                vo.setChild(getChildList(parentGroup.get(vo.getId()),parentGroup));
                vo.setIsParent(true);
            }
        }

        return parent;
    }
    private List<AccountProductVO>  getChildList(List<AccountProductVO> child, Map<Long, List<AccountProductVO>> group){//
        for(AccountProductVO vo:child){
            List<AccountProductVO> groupChild = group.get(vo.getId());
            if(!CollectionUtils.isEmpty(groupChild)){
                vo.setChild(getChildList(groupChild,group));
            }
        }
        return child;
    }

    /**
     * 递归处理
     *
     * @param accountVO  第一层结构对象
     * @param list 全部数据对象
     * @return 树形结构对象
     */
    private List<AccountProductVO> getAccountTree(AccountProductVO accountVO, List<AccountProductVO> list) {
        List<AccountProductVO> accountVOS = new ArrayList<>();
        accountVOS.add(accountVO);
        for (AccountProductVO account : list) {
            // 如果是父子关系
            if (accountVO.getId().equals(account.getParentId())) {

                List<AccountProductVO> child = accountVO.getChild();
                if (CollUtil.isEmpty(child)) {
                    child = new ArrayList<>();
                }
                child.add(account);
                accountVO.setChild(child);
                // 处理子节点
                this.getAccountTree(account, list);
                accountVO.setIsParent(true);
            }
            List<AccountingProduct> accountingProducts = baseMapper.selectList(
                    new LambdaQueryWrapper<AccountingProduct>()
                            .select(AccountingProduct::getId, AccountingProduct::getProductId)
                            .eq(AccountingProduct::getAccountingId, account.getId())
            );
            if (CollUtil.isNotEmpty(accountingProducts)) {
                List<Long> productIds = accountingProducts.stream().map(AccountingProduct::getProductId).collect(Collectors.toList());
                List<Product> products = productMapper.selectList(
                        new LambdaQueryWrapper<Product>().in(Product::getId, productIds)
                );
                if (CollUtil.isNotEmpty(products)) {
                    List<ProductVO> productVOS = BeanUtil.convertList(products, ProductVO.class);
                    account.setProductVOs(productVOS);
                }
            }
        }
        return accountVOS;
    }

    /**
     * 保存或修改会计科目对照
     *
     * @param accountProductSaveDTO 会计科目保存入参
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveAccountProduct(AccountProductSaveDTO accountProductSaveDTO) {
        Long accountId = accountProductSaveDTO.getId();
        // 删除所有原来的关系
        this.remove(new LambdaQueryWrapper<AccountingProduct>().eq(AccountingProduct::getAccountingId, accountId));
        Long hospId = UserContext.getCurrentLoginHospId();
        List<Long> products = accountProductSaveDTO.getProducts();
        // 如果是空表示解绑，不处理更新保存逻辑
        if (CollectionUtils.isEmpty(products)) {
            return;
        }
        List<AccountingProduct> accountingProducts = products.stream().map(i -> {
            AccountingProduct accountingProduct = new AccountingProduct();
            accountingProduct.setAccountingId(accountId)
                    .setProductId(i)
                    .setHospId(hospId)
                    .setCreateTime(System.currentTimeMillis());
            return accountingProduct;
        }).collect(Collectors.toList());

        // 校验已经绑定过的数据 （1：n）
        List<AccountingProduct> list = this.list(
                new LambdaQueryWrapper<AccountingProduct>()
                        .select(AccountingProduct::getId)
//                        .eq(AccountingProduct::getAccountingId, accountId)
                        .eq(AccountingProduct::getHospId, hospId)
                        .in(AccountingProduct::getProductId, accountProductSaveDTO.getProducts())
        );
        if (CollUtil.isNotEmpty(list)) {
            throw new CostException("成本收入id为：" + StrUtil.join(StrUtil.COMMA, list) + "已被其他会计中心绑定，请重新选择");
        }
        this.saveBatch(accountingProducts);
    }
}