package com.kcim.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
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.kcim.common.exception.CostException;
import com.kcim.common.util.BeanUtil;
import com.kcim.common.util.PageUtils;
import com.kcim.common.util.UserContext;
import com.kcim.common.constants.NumberConstant;
import com.kcim.dao.mapper.AccountingMapper;
import com.kcim.dao.mapper.CostShareParamMapper;
import com.kcim.dao.model.Accounting;
import com.kcim.dao.model.CostShareParam;
import com.kcim.dao.model.dto.CostShareParamAccountDto;
import com.kcim.dao.model.dto.CostShareParamEditDto;
import com.kcim.dao.model.dto.CostShareParamSaveDto;
import com.kcim.vo.CostShareParamVO;
import com.kcim.service.CostShareParamService;
import com.kcim.common.constants.Constant;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

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


@Service("costShareParamService")
public class CostShareParamServiceImpl extends ServiceImpl<CostShareParamMapper, CostShareParam> implements CostShareParamService {

    private final AccountingMapper accountingMapper;

    public CostShareParamServiceImpl(AccountingMapper accountingMapper) {
        this.accountingMapper = accountingMapper;
    }

    /**
     * 分页查询相关的分摊参数数据
     *
     * @param current
     * @param pageSize
     * @param name
     * @return
     */
    @Override
    public PageUtils queryList(Integer current, Integer pageSize, String name, Long hospId) {
        Page<CostShareParam> costShareParamPage = new Page<>(current, pageSize);
        Page<CostShareParam> pages = this.page(costShareParamPage, new QueryWrapper<CostShareParam>().lambda()
                .eq(!StringUtils.isEmpty(hospId), CostShareParam::getHospId, hospId)
                .like(!StringUtils.isEmpty(name), CostShareParam::getShareParamName, name).orderByDesc(CostShareParam::getCreateTime));
        List<CostShareParam> records = pages.getRecords();
        List<CostShareParamVO> costShareParamVOList = BeanUtil.convertList(records, CostShareParamVO.class);
        // 封装会计科目Id的集合
        costShareParamVOList.forEach(i -> {
            String accountingId = i.getAccountingId();

            if (StrUtil.isNotBlank(accountingId)) {
                i.setAccountingIds(Arrays.asList(accountingId.split(StrUtil.COMMA)));
            } else {
                i.setAccountingIds(null);
            }
        });
        PageUtils pageUtils = new PageUtils(pages);
        costShareParamVOList.sort(Comparator.comparing(CostShareParamVO::getShareParamCode));
        pageUtils.setList(costShareParamVOList);
        return pageUtils;
    }

    /**
     * 保存分摊参数
     * 保存的时候需要校验分摊参数
     *
     * @param costShareParamSaveDto
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void addCostShareParam(CostShareParamSaveDto costShareParamSaveDto) {
        //检验分摊参数是存在
        getCostShareParamByCode(costShareParamSaveDto);
        CostShareParam costShareParam = BeanUtil.convertObj(costShareParamSaveDto, CostShareParam.class);
        costShareParam.setCreateTime(System.currentTimeMillis());
        baseMapper.insert(costShareParam);
    }

    /**
     * 检验分摊参数是存在
     */
    private void getCostShareParamByCode(CostShareParamSaveDto costShareParamSaveDto) {
        List<CostShareParam> costShareParamList = baseMapper.selectList(new QueryWrapper<CostShareParam>().lambda()
                .eq(CostShareParam::getHospId, costShareParamSaveDto.getHospId()));
        // 检验添加的分摊参数是否存在
        if (!CollectionUtils.isEmpty(costShareParamList)) {
            Map<String, List<CostShareParam>> costShareMap = costShareParamList.stream().collect(Collectors.groupingBy(CostShareParam::getShareParamCode));
            if (!CollectionUtils.isEmpty(costShareMap.get(costShareParamSaveDto.getShareParamCode()))) {
                throw new CostException(500, "分摊参数已存在");
            }
        }
    }

    /**
     * 修改分摊参数
     *
     * @param costShareParamEditDto
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateCostShareParam(CostShareParamEditDto costShareParamEditDto) {
        Long id = costShareParamEditDto.getId();
        CostShareParam costShareParam = baseMapper.selectById(id);
        if (Objects.isNull(costShareParam)) {
            throw new CostException(500, "对不起分摊参数不存在");
        }
        baseMapper.deleteById(id);
        // 判断当前输入的Code以最初的Code是否一样
        List<CostShareParam> costShareParamList = baseMapper.selectList(new QueryWrapper<CostShareParam>().lambda().select(CostShareParam::getShareParamCode).eq(CostShareParam::getHospId, costShareParamEditDto.getHospId()));
        Map<String, List<CostShareParam>> map = costShareParamList.stream().collect(Collectors.groupingBy(CostShareParam::getShareParamCode));
        if (!CollectionUtils.isEmpty(map.get(costShareParamEditDto.getShareParamCode()))) {
            throw new CostException(500, "对不起分摊参数代码已存在");
        }
        CostShareParam costShareParamRequest = BeanUtil.convertObj(costShareParamEditDto, CostShareParam.class);
        costShareParamRequest.setId(null);
        costShareParamRequest.setCreateTime(System.currentTimeMillis());
        if (NumberConstant.ONE.equals(costShareParamEditDto.getShareParamCode()) && NumberConstant.ONE.equals(costShareParamEditDto.getShareParamCode())) {
            costShareParamRequest.setAccountingId(costShareParam.getAccountingId());
        }
        baseMapper.insert(costShareParamRequest);
    }

    /**
     * 为按照科目的计算方式添加成本科目
     *
     * @param costShareParamAccountDto
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public CostShareParam updateCostShareParamByAccountId(CostShareParamAccountDto costShareParamAccountDto) {
        Long hospId = UserContext.getHospId();
        Long costShareParamId = costShareParamAccountDto.getCostShareParamId();
        CostShareParam costShareParam = baseMapper.selectById(costShareParamId);
        List<String> accoutingCodes = new LinkedList<>();
        Map<Long, String> accountingMap = accountingMapper.selectList(new QueryWrapper<Accounting>().lambda().eq(Accounting::getHospId, hospId)).stream().collect(Collectors.toMap(Accounting::getId, Accounting::getAccountingCode));
        //  判断当前操作的分层参数的计算方式是不是按科目计算
        if (NumberConstant.TWO.equals(costShareParam.getCalcType())) {
            String[] accountIds = costShareParamAccountDto.getAccountIds();
            List<String> accountList = Arrays.asList(accountIds);
            if (!CollectionUtil.isEmpty(accountList)) {
                String accountingIds = accountList.stream().map(String::valueOf).collect(Collectors.joining(StrUtil.COMMA));
                costShareParam.setAccountingId(accountingIds);
                accountList.forEach(i -> {
                    String accountCode = accountingMap.get(Long.parseLong(i));
                    accoutingCodes.add(accountCode);
                });
                costShareParam.setAccountingCodes(accoutingCodes.stream().map(String::valueOf).collect(Collectors.joining(StrUtil.COMMA)));
            } else {
                costShareParam.setAccountingId(null);
            }
            baseMapper.updateById(costShareParam);
        } else {
            throw new CostException(500, "计算方式不是按会计科目计算");
        }
        return null;
    }

    /**
     * 获取所有分摊参数的集合信息
     *
     * @param hospId
     * @return
     */
    @Override
    @ApiOperation("获取所有的分摊参数的集合数据")
    public List<CostShareParamVO> getAll(Long hospId) {
        List<CostShareParam> costShareParamList = baseMapper.selectList(new QueryWrapper<CostShareParam>().lambda()
                .eq(CostShareParam::getHospId, hospId));
        return BeanUtil.convertList(costShareParamList, CostShareParamVO.class);
    }

    /**
     * 根据医院的Id分摊参数的ID获取对应的分摊参数的数据
     *
     * @param id
     * @param hospId
     * @return
     */
    @Override
    public CostShareParamVO getByHospIdAndAPramId(Integer id, Long hospId) {
        CostShareParam costShareParam = baseMapper.selectOne(new QueryWrapper<CostShareParam>().lambda()
                .eq(CostShareParam::getHospId, hospId)
                .eq(CostShareParam::getId, id));
        CostShareParamVO costShareParamVO = BeanUtil.convertObj(costShareParam, CostShareParamVO.class);
        return costShareParamVO;
    }

    @Override
    public List<Long> selectIsSelect(Integer shareParamId) {
        CostShareParam byId = this.getById(shareParamId);
        if (Objects.isNull(byId)) {
            return Collections.emptyList();
        }
        String accountingId = byId.getAccountingId();
        if (!StringUtils.isEmpty(accountingId)) {
            String[] split = accountingId.split(StrUtil.COMMA);
            List<Long> accountingIdList = Arrays.stream(split).map(Long::valueOf).collect(Collectors.toList());
            return accountingIdList;
        } else {
            return Collections.emptyList();
        }


    }

    /**
     * 通过计算方式和id获取是否存在会计科目的成本分摊参数
     *
     * @param shareParamId 主键id
     * @return CostShareParam
     */
    @Override
    public CostShareParam getByIdAndCalcType(Long shareParamId) {
        return this.getOne(
                new LambdaQueryWrapper<CostShareParam>().eq(CostShareParam::getId, shareParamId).eq(CostShareParam::getCalcType, 2)
        );
    }

    /**
     * 通过code得到name
     *
     * @param shareParamCode
     * @param hospId
     * @return
     */
    @Override
    public String getByCode(String shareParamCode, Long hospId) {
        CostShareParam one = this.getOne(
                new LambdaQueryWrapper<CostShareParam>().eq(CostShareParam::getShareParamCode, shareParamCode)
                        .eq(CostShareParam::getHospId, hospId).last(Constant.LIMIT)
        );
        if (Objects.isNull(one)) {
            throw new CostException("数据异常");
        }
        return one.getShareParamName();
    }

    /**
     * 批量删除分摊参数
     *
     * @param asList 分摊参数的Id集合
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void deleteByIds(List<Integer> asList) {
        this.removeByIds(asList);
    }
}