package com.kcim.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
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.constants.NumberConstant;
import com.kcim.dao.mapper.CostIncomeGroupSetMapper;
import com.kcim.dao.model.Accounting;
import com.kcim.dao.model.CostIncomeGroupSet;
import com.kcim.dao.model.Responsibility;
import com.kcim.dao.model.dto.CostIncomeGroupSetEditDto;
import com.kcim.dao.model.dto.CostIncomeGroupSetSaveDto;
import com.kcim.dao.model.dto.IncomeAccountDto;
import com.kcim.vo.AccountIncomeSetVO;
import com.kcim.vo.CostIncomeGroupSetVO;
import com.kcim.service.AccountingService;
import com.kcim.service.CostIncomeGroupSetService;
import com.kcim.service.ResponsibilityService;
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 org.springframework.web.bind.annotation.RequestParam;

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


@Service("costIncomeGroupSetService")
public class CostIncomeGroupSetServiceImpl extends ServiceImpl<CostIncomeGroupSetMapper, CostIncomeGroupSet> implements CostIncomeGroupSetService {

    private final ResponsibilityService responsibilityService;

    private final AccountingService accountingService;

    public CostIncomeGroupSetServiceImpl(ResponsibilityService responsibilityService, AccountingService accountingService) {
        this.responsibilityService = responsibilityService;
        this.accountingService = accountingService;
    }

    /**
     * 分页查询
     *
     * @param current 当前页
     * @param pageSize 每一页大小
     * @param hospId 医院Id
     * @return PageUtils
     */
    @Override
    public PageUtils queryList(Integer current, Integer pageSize, Long hospId) {
        Page<CostIncomeGroupSet> costIncomeGroupSetPage = new Page<>(current, pageSize);
        Page<CostIncomeGroupSet> pages = this.page(costIncomeGroupSetPage, new QueryWrapper<CostIncomeGroupSet>().lambda()
                .eq(CostIncomeGroupSet::getHospId, hospId)
                .orderByDesc(CostIncomeGroupSet::getCreateTime));
        List<CostIncomeGroupSet> records = pages.getRecords();
        List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                .eq(Responsibility::getHospId, hospId));
        List<CostIncomeGroupSetVO> costIncomeGroupSetVOList = BeanUtil.convertList(records, CostIncomeGroupSetVO.class);
        if (!CollectionUtils.isEmpty(responsibilityList)) {
            final Map<String, String> listMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getResponsibilityName));
            costIncomeGroupSetVOList.forEach(i -> {
                List<String> responsibilityNameList = new LinkedList<>();
                String responsibilityCode = i.getResponsibilityCodes();
                if (!StringUtils.isEmpty(responsibilityCode)){
                    List<String> responsibilityCodeList = Arrays.asList(responsibilityCode.split(StrUtil.SLASH));
                    if (!CollectionUtils.isEmpty(responsibilityCodeList)) {
                        responsibilityCodeList.forEach(m->{
                            responsibilityNameList.add(listMap.get(m));
                        });
                    }
                    i.setResponsibilityName(String.join("/", responsibilityNameList));
                }
                if (NumberConstant.ONE.equals(i.getOpenDepartmentStatus()) && NumberConstant.ONE.equals(i.getStartDepartmentStatus())){
                    i.setAccountStatus(NumberConstant.ONE);
                }else {
                    i.setAccountStatus(NumberConstant.ZERO);
                }
            });
        }
        PageUtils pageUtils = new PageUtils(pages);
        pageUtils.setList(costIncomeGroupSetVOList);
        return pageUtils;
    }

    /**
     * 根据Id获取对应的收入归集设置的数据
     *
     * @param id 收入归集设置的Id
     * @param hospId 医院的Id
     * @return CostIncomeGroupSetVO
     */
    @Override
    public CostIncomeGroupSetVO getByIncomeGroupId(Long id, Long hospId) {
        CostIncomeGroupSet costIncomeGroupSet = baseMapper.selectById(id);
        if (Objects.isNull(costIncomeGroupSet)) {
            return null;
        }
        CostIncomeGroupSetVO costIncomeGroupSetVO = BeanUtil.convertObj(costIncomeGroupSet, CostIncomeGroupSetVO.class);
        List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                .eq(Responsibility::getHospId, hospId));
        if (!CollectionUtils.isEmpty(responsibilityList)) {
            Map<String, String> listMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getResponsibilityName));
            String responsibilityCode = costIncomeGroupSetVO.getResponsibilityCodes();
            if (!StringUtils.isEmpty(responsibilityCode)) {
                List<String> asList = Arrays.asList(responsibilityCode.split(StrUtil.SLASH));
                if (!CollectionUtils.isEmpty(asList)){
                    String responsibilities = listMap.get(asList.get(asList.size()-1));
                    costIncomeGroupSetVO.setResponsibilityName(responsibilities);
                }
            }
        }
        return costIncomeGroupSetVO;
    }

    /**
     * 保存收入归集设置的数据
     *
     * @param costIncomeGroupSetSaveDto
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void addCostIncomeGroupSet(CostIncomeGroupSetSaveDto costIncomeGroupSetSaveDto, Long hospId) {
        // 检验输入的数据是否符合要求
        checkIncomeGroupSet(costIncomeGroupSetSaveDto, hospId);
        CostIncomeGroupSet costIncomeGroupSet = BeanUtil.convertObj(costIncomeGroupSetSaveDto, CostIncomeGroupSet.class);
        costIncomeGroupSet.setCreateTime(System.currentTimeMillis());
        costIncomeGroupSet.setHospId(hospId);
        baseMapper.insert(costIncomeGroupSet);
    }

    /**
     * 检验输入的数据是否符合要求
     * @param costIncomeGroupSetSaveDto 需要保存的收入归集设置的数据
     * @param hospId 医院Id
     */
    private void checkIncomeGroupSet(CostIncomeGroupSetSaveDto costIncomeGroupSetSaveDto, Long hospId) {
        Integer sum = costIncomeGroupSetSaveDto.getOpenDepartmentProportion() + costIncomeGroupSetSaveDto.getStartDepartmentProportion();
        if (!NumberConstant.ONE_HUNDRED.equals(sum)) {
            if ((NumberConstant.ONE.equals(costIncomeGroupSetSaveDto.getOpenDepartmentStatus()) || NumberConstant.ONE.equals(costIncomeGroupSetSaveDto.getStartDepartmentStatus()))){
                throw new CostException(500, "输入的比例和不是100");
            }
        }
        if (NumberConstant.TWO.equals(costIncomeGroupSetSaveDto.getOpenDepartmentStatus())
                && NumberConstant.TWO.equals(costIncomeGroupSetSaveDto.getStartDepartmentStatus())) {
            if (StringUtils.isEmpty(costIncomeGroupSetSaveDto.getResponsibilityCodes())){
                throw new CostException(500, "请选择要归属到的责任中心");
            }else {
                costIncomeGroupSetSaveDto.setOpenDepartmentProportion(NumberConstant.ZERO);
                costIncomeGroupSetSaveDto.setStartDepartmentProportion(NumberConstant.ZERO);
            }
        }
        if (!StringUtils.isEmpty(costIncomeGroupSetSaveDto.getResponsibilityCodes())){
            if (NumberConstant.ONE.equals(costIncomeGroupSetSaveDto.getOpenDepartmentStatus()) ||
                NumberConstant.ONE.equals(costIncomeGroupSetSaveDto.getStartDepartmentStatus())){
                throw new CostException(500,"存在收益中心 不允许设置责任中心");
            }
        }
        // 检验原始数据里面是否存在
        List<CostIncomeGroupSet> costIncomeGroupSets = baseMapper.selectList(new QueryWrapper<CostIncomeGroupSet>().lambda()
                .eq(CostIncomeGroupSet::getHospId, hospId));
        List<CostIncomeGroupSet> costIncomeGroupSetList = costIncomeGroupSets.stream().filter(i ->
                i.getOpenDepartmentStatus().equals(costIncomeGroupSetSaveDto.getOpenDepartmentStatus()) &&
                        i.getStartDepartmentStatus().equals(costIncomeGroupSetSaveDto.getStartDepartmentStatus())
        ).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(costIncomeGroupSetList)){
            throw new CostException(500,"开单与执行的对应类型已经存在");
        }
        // 如果一个是收入中心一个是成本中心  那本自动调整比例设置为0 100  如果两个收益中心的话需要按照不理  都是成本中心就是0
        if (!costIncomeGroupSetSaveDto.getOpenDepartmentStatus().equals(costIncomeGroupSetSaveDto.getStartDepartmentStatus())){
            if (NumberConstant.ONE.equals(costIncomeGroupSetSaveDto.getOpenDepartmentStatus())){
                costIncomeGroupSetSaveDto.setOpenDepartmentProportion(NumberConstant.ONE_HUNDRED);
                costIncomeGroupSetSaveDto.setStartDepartmentProportion(NumberConstant.ZERO);
            }else {
                costIncomeGroupSetSaveDto.setOpenDepartmentProportion(NumberConstant.ZERO);
                costIncomeGroupSetSaveDto.setStartDepartmentProportion(NumberConstant.ONE_HUNDRED);
            }
        }
    }

    /**
     * 修改收入归集设置的数据
     *
     * @param costIncomeGroupSetEditDto 需要修改的收入归集设置的数据
     * @param hospId 医院Id
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void updateByIncomeGroup(CostIncomeGroupSetEditDto costIncomeGroupSetEditDto, Long hospId) {
        Long id = costIncomeGroupSetEditDto.getId();
        CostIncomeGroupSet costIncomeGroupSet = baseMapper.selectById(id);
        if (Objects.isNull(costIncomeGroupSet)) {
            throw new CostException(500, "收入归集设置数据不存在");
        }
        baseMapper.deleteById(id);
        CostIncomeGroupSetSaveDto costIncomeGroupSetSaveDto = BeanUtil.convertObj(costIncomeGroupSetEditDto, CostIncomeGroupSetSaveDto.class);
        // 检验输入的数据是否存在
        checkIncomeGroupSet(costIncomeGroupSetSaveDto,hospId);
        CostIncomeGroupSet incomeGroupSet = BeanUtil.convertObj(costIncomeGroupSetSaveDto, CostIncomeGroupSet.class);
        incomeGroupSet.setHospId(hospId);
        incomeGroupSet.setCreateTime(System.currentTimeMillis());
        incomeGroupSet.setResponsibilityCodes(costIncomeGroupSetSaveDto.getResponsibilityCodes());
        incomeGroupSet.setAccountCode(costIncomeGroupSet.getAccountCode());
        baseMapper.insert(incomeGroupSet);
    }

    /**
     * 查询当前收入归集设置里面对应的会计科目的Id集合
     *
     * @param incomeGroutSetId 收入归集设置的Id
     * @return List<String>
     */
    @Override
    public List<String> selectIsSelect(Integer incomeGroutSetId) {
        CostIncomeGroupSet incomeGroupSet = this.getById(incomeGroutSetId);
        if (Objects.isNull(incomeGroupSet)) {
            return Collections.emptyList();
        }
        String accountCode = incomeGroupSet.getAccountCode();
        if (!StringUtils.isEmpty(accountCode)){
            return Arrays.stream(accountCode.split(StrUtil.COMMA)).map(String::valueOf).collect(Collectors.toList());
        }else {
            return Collections.emptyList();
        }
    }

    /**
     * 设置对应的排除成本科目
     * @param incomeAccountDto 需要排除的会计科目数据对象
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void updateAccountCode(IncomeAccountDto incomeAccountDto) {
        Long id = incomeAccountDto.getId();
        List<String> accountCodeList = Arrays.asList(incomeAccountDto.getAccountCodes());
        CostIncomeGroupSet incomeGroupSet = this.getById(id);
        if (Objects.isNull(incomeGroupSet)){
            throw new CostException(500,"收入归集设置不存在");
        }
        if (NumberConstant.TWO.equals(incomeGroupSet.getOpenDepartmentStatus())|| NumberConstant.TWO.equals(incomeGroupSet.getStartDepartmentStatus())){
            throw new CostException(500,"存在成本中心 不允许设置排除的会计科目");
        }
        if(CollUtil.isNotEmpty(accountCodeList)){
            String accountCodes = accountCodeList.stream().map(String::valueOf).collect(Collectors.joining(StrUtil.COMMA));
            incomeGroupSet.setAccountCode(accountCodes);
        }else{
            incomeGroupSet.setAccountCode(null);
        }
        baseMapper.updateById(incomeGroupSet);
    }

    /**
     * 所有的会计科目里面与当前收入归集设置有关联的数据
     *
     * @param id     当前收入归集设置的Id
     * @param hospId 当前医院的Id
     * @return
     */
    @Override
    public List<AccountIncomeSetVO> getIncomeAccountStatus(@RequestParam(value = "id")Long id, Long hospId) {

        CostIncomeGroupSet incomeGroupSet = this.getById(id);
        if (Objects.isNull(incomeGroupSet)){
            throw new CostException(500,"收入归集设置不存在");
        }
        String accountCode = incomeGroupSet.getAccountCode();
        List<AccountIncomeSetVO> accountIncomeSetVOList = null;
        if (StrUtil.isNotBlank(accountCode)){
            List<String> accountCodList = Arrays.asList(accountCode.split(StrUtil.COMMA));
            List<Accounting> accountingList = accountingService.list(new QueryWrapper<Accounting>().lambda()
                    .eq(Accounting::getHospId, hospId)
                    .in(Accounting::getAccountingCode,accountCodList));
            accountIncomeSetVOList = BeanUtil.convertList(accountingList, AccountIncomeSetVO.class);
        }
        return accountIncomeSetVOList;
    }

}