package com.kcim.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kcim.common.constants.NumberConstant;
import com.kcim.common.enums.ReportItemTypeEnum;
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.dao.model.*;
import com.kcim.dao.model.dto.ComputeItemGroupByOrder;
import com.kcim.dao.model.dto.ComputeOrderCostPageDto;
import com.kcim.dao.repository.ComputeItemCostRepository;
import com.kcim.dao.repository.ImportPatientInfoRepository;
import com.kcim.dao.repository.OrderCostDetailRepository;
import com.kcim.dao.repository.OrderCostRepository;
import com.kcim.service.ComputeItemCostService;
import com.kcim.service.OrderCostService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

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


@Service("OrderCostService")
@Slf4j
@AllArgsConstructor
public class OrderCostServiceImpl  implements OrderCostService {

    OrderCostRepository repository;

    OrderCostDetailRepository detailRepository;

    ImportPatientInfoRepository importPatientInfoRepository;

    ComputeItemCostRepository computeItemCostRepository;

    ComputeItemCostService computeItemCostService;
    /**
     * @param current 当前页
     * @param pageSize 页容量
     * @param computeDate 核算年月
     * @param orderName 医嘱名称
     * @return 医嘱计算列表
     */
    @Override
    public Object orderCostCalculateList(Integer current, Integer pageSize, String computeDate, String orderName) {
        Page<ComputeOrderCostPageDto> page = repository.getByPage(current, pageSize, computeDate, orderName);
        if(CollectionUtils.isEmpty(page.getRecords())){
            return new PageUtils(new ArrayList<>(), NumberConstant.ZERO,pageSize,current);
        }
        return new PageUtils(page.getRecords(), Math.toIntExact(page.getTotal()),pageSize,current);
    }

    /**
     * 计算医嘱项目成本
     * @param computeDate 核算年月
     */
    @Override
    public void orderCostCalculate(String computeDate) {
        //获取患者信息
        List<ImportPatientInfo> patientInfos = importPatientInfoRepository.getByComputeDate(computeDate);
        if(CollectionUtils.isEmpty(patientInfos)){
            throw new CostException("当前核算年月未导入患者信息");
        }
        List<ComputeItemGroupByOrder> itemCostList = computeItemCostRepository.getByComputeDateGroupByOrder(computeDate);
        if (CollectionUtils.isEmpty(itemCostList)){
            throw new CostException("收费项目成本未计算，请先计算收费项目成本");

        }
        Map<String,ImportPatientInfo> patientInfoMap = patientInfos.stream().collect(Collectors.toMap(ImportPatientInfo::getVisitNo, importPatientInfo -> importPatientInfo, (a, b) -> b));


        //组装患者所在科室
        for (ComputeItemGroupByOrder groupByOrder : itemCostList) {
            groupByOrder.setDepartCode(patientInfoMap.get(groupByOrder.getVisitNo()).getDepartmentCode());
            groupByOrder.setDepartName(patientInfoMap.get(groupByOrder.getVisitNo()).getDepartmentName());
        }
        //按医嘱分组
        Map<String, List<ComputeItemGroupByOrder>> collect = itemCostList.stream().collect(Collectors.groupingBy(ComputeItemGroupByOrder::getOrderCode));
        OrderCost orderCost = new OrderCost();
        orderCost.setComputeDate(computeDate);
        orderCost.setHospId(UserContext.getHospId());
        orderCost.setCreateUser(String.valueOf(UserContext.getCurrentUser().getId()));
        orderCost.setCreateTime(new Date());
        OrderCostDetail orderCostDetail = new OrderCostDetail();
        orderCostDetail.setHospId(UserContext.getHospId());
        orderCostDetail.setCreateUser(String.valueOf(UserContext.getCurrentUser().getId()));
        orderCostDetail.setCreateTime(new Date());

        final int[] index = {0};
        List<OrderCost> saveOrderCost = new ArrayList<>();
        List<OrderCostDetail> details = new ArrayList<>();
        //按科室分组
        collect.forEach((orderCode,orderValue)->{
            String orderName = orderValue.get(0).getOrderName();
            Map<String, List<ComputeItemGroupByOrder>> collect1 = orderValue.stream().collect(Collectors.groupingBy(ComputeItemGroupByOrder::getDepartCode));
            //科室下所有数据求和
            collect1.forEach((departCode,departValue)->{
                String departName = departValue.get(0).getDepartName();
                OrderCost order = BeanUtil.convertObj(orderCost, OrderCost.class);
                order.setCode(orderCode);
                order.setName(orderName);
                order.setDepartmentCode(departCode);
                order.setDepartmentName(departName);
                order.setIndex(index[0]);
                getDetails(orderCostDetail, index[0], details, departValue);
                saveOrderCost.add(order);
                index[0]++;
            });

        });
        if(!CollectionUtils.isEmpty(saveOrderCost)){
            //作废当前核算年月已有数据
            List<Integer> integers = repository.removeByComputeDate(computeDate);
            if(!CollectionUtils.isEmpty(integers)){
                detailRepository.removeByOrderCostId(integers);
            }
            repository.saveBatch(saveOrderCost,100);
            if(!CollectionUtils.isEmpty(saveOrderCost)){
                Map<Integer,Integer> indexId = saveOrderCost.stream().collect(Collectors.toMap(OrderCost::getIndex, OrderCost::getId, (a, b) -> b));
                Map<Integer, List<OrderCostDetail>> indexGroup = details.stream().collect(Collectors.groupingBy(OrderCostDetail::getIndex));
                List<OrderCostDetail> saveCostDetails = new ArrayList<>();
                indexGroup.keySet().forEach(integer -> {
                    Integer costId = indexId.get(integer);
                    List<OrderCostDetail> detailList = indexGroup.get(integer);
                    detailList.forEach(detail -> detail.setOrderCostId(costId));
                    saveCostDetails.addAll(detailList);
                });
                detailRepository.saveBatch(saveCostDetails,500);
            }
        }

    }

    private void getDetails(OrderCostDetail orderCostDetail, int index, List<OrderCostDetail> details, List<ComputeItemGroupByOrder> departmentList) {
        //药品收入
        BigDecimal drugIncome = new BigDecimal("0.0000");
        //材料收入
        BigDecimal materialIncome = new BigDecimal("0.0000");
        //项目收入
        BigDecimal itemIncome = new BigDecimal("0.0000");
        //药品成本
        BigDecimal drugCost = new BigDecimal("0.0000");
        //材料成本
        BigDecimal materialCost = new BigDecimal("0.0000");
        //项目成本
        BigDecimal itemCost = new BigDecimal("0.0000");
        //人力成本
        BigDecimal empCost = new BigDecimal("0.0000");
        //设备成本
        BigDecimal equipmentCost = new BigDecimal("0.0000");
        //空间成本
        BigDecimal spaceCost = new BigDecimal("0.0000");
        for (ComputeItemGroupByOrder computeItemGroupByOrder : departmentList) {
            drugIncome = drugIncome.add(computeItemGroupByOrder.getDrugIncome());
            materialIncome = materialIncome.add(computeItemGroupByOrder.getMaterialIncome());
            itemIncome = itemIncome.add(computeItemGroupByOrder.getItemIncome());
            drugCost = drugCost.add(computeItemGroupByOrder.getDrugCost());
            materialCost = materialCost.add(computeItemGroupByOrder.getMaterialCost());
            itemCost = itemCost.add(computeItemGroupByOrder.getItemCost());
            empCost = empCost.add(computeItemGroupByOrder.getEmpCost());
            equipmentCost = equipmentCost.add(computeItemGroupByOrder.getEquipmentCost());
            spaceCost = spaceCost.add(computeItemGroupByOrder.getSpaceCost());
        }
        List<String> itemTypeList = computeItemCostService.getItemTypeList();
        for (String s : itemTypeList) {
            OrderCostDetail detail = BeanUtil.convertObj(orderCostDetail, OrderCostDetail.class);
            detail.setType(s);
            detail.setIndex(index);
            if(s.equals(ReportItemTypeEnum.DRUG_INCOME.getCode())){
                detail.setComputeResult(drugIncome);
            }else if (s.equals(ReportItemTypeEnum.MATERIAL_INCOME.getCode())) {
                detail.setComputeResult(materialIncome);
            }else if (s.equals(ReportItemTypeEnum.ITEM_INCOME.getCode())) {
                detail.setComputeResult(itemIncome);
            }else if (s.equals(ReportItemTypeEnum.DRUG_COST.getCode())) {
                detail.setComputeResult(drugCost);
            }else if (s.equals(ReportItemTypeEnum.MATERIAL_COST.getCode())) {
                detail.setComputeResult(materialCost);
            }else if (s.equals(ReportItemTypeEnum.ITEM_COST.getCode())) {
                detail.setComputeResult(itemCost);
            }else if (s.equals(ReportItemTypeEnum.EMP_COST.getCode())) {
                detail.setComputeResult(empCost);
            }else if (s.equals(ReportItemTypeEnum.EQUIPMENT_COST.getCode())) {
                detail.setComputeResult(equipmentCost);
            }else if (s.equals(ReportItemTypeEnum.SPACE_COST.getCode())) {
                detail.setComputeResult(spaceCost);
            }  else {
                detail.setComputeResult(BigDecimal.ZERO);
            }
            details.add(detail);
        }
    }
}