package com.casic.missiles.service.Impl.business;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
import com.casic.missiles.core.model.auth.AuthUser;
import com.casic.missiles.core.page.PageFactory;
import com.casic.missiles.core.shiro.ShiroKit;
import com.casic.missiles.dto.business.dispatch.DeviceDispatchDTO;
import com.casic.missiles.dto.business.dispatch.DeviceDispatchVO;
import com.casic.missiles.dto.business.labExecutive.MeasureProcessDTO;
import com.casic.missiles.dto.business.labExecutive.SampleHandOutListRequest;
import com.casic.missiles.dto.business.labExecutive.SampleHandOutListResponse;
import com.casic.missiles.dto.business.workbench.SampleMeasureChartResponse;
import com.casic.missiles.dto.business.workbench.SampleMeasureResponse;
import com.casic.missiles.dto.business.workbench.SampleMonitorResponse;
import com.casic.missiles.dto.business.workbench.SampleStatusMonthResponse;
import com.casic.missiles.enums.BusinessExceptionEnum;
import com.casic.missiles.enums.business.MeasureStatusEnum;
import com.casic.missiles.enums.sample.SampleStatusEnum;
import com.casic.missiles.enums.system.ApprovalStatusEnum;
import com.casic.missiles.exception.BusinessException;
import com.casic.missiles.mapper.business.BusinessCertificateReportMapper;
import com.casic.missiles.mapper.business.BusinessLabExecutiveInfoMapper;
import com.casic.missiles.mapper.business.BusinessOrderSampleRelationMapper;
import com.casic.missiles.mapper.meter.MeterStaffMapper;
import com.casic.missiles.model.business.BusinessCertificateReport;
import com.casic.missiles.model.meter.MeterStaff;
import com.casic.missiles.service.business.BusinessWorkbenchService;
import com.casic.missiles.utils.DictCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

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

/**
 * @Description:
 * @Author: wangpeng
 * @Date: 2023/4/19 14:01
 */
@Slf4j
@Service
public class BusinessWorkbenchServiceImpl implements BusinessWorkbenchService {
    @Autowired
    private BusinessOrderSampleRelationMapper orderSampleRelationMapper;
    @Autowired
    private BusinessLabExecutiveInfoMapper labExecutiveInfoMapper;
    @Autowired
    private MeterStaffMapper staffMapper;
    @Autowired
    private BusinessCertificateReportMapper certificateReportMapper;

    @Override
    public Page<SampleMonitorResponse> sampleMonitorListPage(Page<SampleMonitorResponse> page) {
        Page<SampleMonitorResponse> sampleList = orderSampleRelationMapper.selectSampleMonitorListByStatus(page, SampleStatusEnum.IN_MEASURE);
        List<SampleMonitorResponse> records = sampleList.getRecords();
        if(CollectionUtils.isEmpty(records)){
            return new Page<>();
        }
        records.parallelStream().forEach(sample -> {
            Long orderId = sample.getOrderId();
            Long sampleId = sample.getSampleId();
            List<MeasureProcessDTO> measureProcessDTOS = labExecutiveInfoMapper.selectExecutiveList(orderId, sampleId);
            if (CollectionUtils.isEmpty(measureProcessDTOS)) {
                log.info("业务工作台样品监控-样品检测中状态不存在当前进行检测的实验室，orderId：{}，sampleId：{}", orderId, sampleId);
                return;
            }
            List<String> statusList = new ArrayList<>();
            statusList.add(MeasureStatusEnum.TO_ALLOCATE);
            statusList.add(MeasureStatusEnum.TO_MEASURE);
            statusList.add(MeasureStatusEnum.IN_MEASURE);
            measureProcessDTOS.forEach(measureProcessDTO -> {
                if(statusList.contains(measureProcessDTO.getMeasureStatus())){
                    sample.setCurrentSegment(measureProcessDTO.getMeasureSegment());
                    sample.setCurrentNo(measureProcessDTO.getMeasureSequence());
                    return;
                }
            });
            if(Objects.isNull(sample.getCurrentSegment())){
                return;
            }
            //获取当前检测实验室及下一检测实验室
            List<MeasureProcessDTO> collect = measureProcessDTOS.stream().filter(s -> {
                if (Objects.isNull(s.getMeasureSequence()) || Objects.isNull(sample.getCurrentNo())) {
                    return false;
                }
                Integer nextNo = sample.getCurrentNo() + 1;
                return nextNo.equals(s.getMeasureSequence());
            }).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(collect)){
                sample.setNextSegment(collect.get(0).getMeasureSegment());
                int size = measureProcessDTOS.size();
                //计算进度
                String progress = BigDecimal.valueOf(sample.getCurrentNo()).multiply(BigDecimal.valueOf(100)).divide(BigDecimal.valueOf(size), 2, BigDecimal.ROUND_HALF_UP).toPlainString() + "%";
                sample.setProgress(progress);
            }
        });
        return sampleList;
    }

    @Override
    public Page<SampleMeasureResponse> sampleMeasureListPage(Page<SampleMeasureResponse> page) throws Exception {
        AuthUser authUser = ShiroKit.getUser();
        Assert.isFalse(Objects.isNull(authUser), () -> {
            throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED);
        });
        MeterStaff meterStaff = getMeterStaffInfo(authUser);
        Page<SampleMeasureResponse> sampleMeasurePage = new Page<>();
        //计量人员只能查看自己的检测样品
        if(Objects.nonNull(meterStaff)) {
            //实验室组长查看部门检测
            Map<String, Object> resultMap = selectDirectDept(authUser);
            if(!CollectionUtils.isEmpty(resultMap) && Objects.nonNull(resultMap.get("deptId"))) {
                Long deptId = (Long) resultMap.get("deptId");
                sampleMeasurePage = labExecutiveInfoMapper.selectListByDeptId(page, deptId);
            }else {
                //组员查看我的检测
                Long userId = meterStaff.getId();
                sampleMeasurePage = labExecutiveInfoMapper.selectListByUserId(page, userId);
            }
        }else {
            //非计量人员可以查看全部的检测样品
            sampleMeasurePage = labExecutiveInfoMapper.selectAllList(page);
        }
        if(Objects.isNull(sampleMeasurePage) || CollectionUtils.isEmpty(sampleMeasurePage.getRecords())){
            return new Page<>();
        }
        for (SampleMeasureResponse record : sampleMeasurePage.getRecords()) {
            DictCodeUtils.convertDictMultiCodeToName(record);
        }
        return sampleMeasurePage;
    }

    @Override
    public List<SampleMeasureChartResponse> sampleMeasureChart() throws Exception {
        //当月检测列表按待检测、检测中、检测完3种状态分组
        List<SampleMeasureChartResponse> list = labExecutiveInfoMapper.selectListGroupByStatus();
        if(CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        int sum = list.stream().mapToInt(s -> s.getMeasureQuantity()).sum();
        for (SampleMeasureChartResponse chartResponse : list) {
            DictCodeUtils.convertDictMultiCodeToName(chartResponse);
            chartResponse.setTotalQuantity(sum);
            String rate = BigDecimal.valueOf(chartResponse.getMeasureQuantity()).multiply(BigDecimal.valueOf(100)).divide(BigDecimal.valueOf(sum), 2, BigDecimal.ROUND_HALF_UP).toPlainString() + "%";
            chartResponse.setRate(rate);
        }
        return list;
    }

    @Override
    public List<SampleStatusMonthResponse> sampleStatusMonth() {
        //待收入，本月使用预计送达时间计算
        Page<DeviceDispatchVO> page = PageFactory.defaultPage();
        DeviceDispatchDTO request = new DeviceDispatchDTO();
        request.setSampleStatus(SampleStatusEnum.TO_RECEIVE);
        Page<DeviceDispatchVO> dispatchVoPage = orderSampleRelationMapper.getSampleListByStatusMonth(page, request);
        //待分发、检测中，本月使用更新的时间
        Page<SampleHandOutListResponse> handOutPage = PageFactory.defaultPage();
        SampleHandOutListRequest handOutListRequest = new SampleHandOutListRequest();
        handOutListRequest.setSampleStatus(SampleStatusEnum.TO_HANDOUT);
        Page<SampleHandOutListResponse> toList = orderSampleRelationMapper.selectSampleListByStatusMonth(handOutPage, handOutListRequest);
        SampleStatusMonthResponse response2 = new SampleStatusMonthResponse();
        response2.setStatus("待分发");
        response2.setQuantity(toList.getTotal());
        handOutListRequest.setSampleStatus(SampleStatusEnum.IN_MEASURE);
        Page<SampleHandOutListResponse> inList = orderSampleRelationMapper.selectSampleListByStatusMonth(handOutPage, handOutListRequest);
        //成编制报告，非草稿的，本月使用报告完成的出具日期
        QueryWrapper<BusinessCertificateReport> wrapper = new QueryWrapper<>();
        String dateformat = "yyyy-MM-dd";
        SimpleDateFormat f = new SimpleDateFormat(dateformat);
        String startDate = f.format(DateUtil.beginOfMonth(new Date()));
        String endDate = f.format(new Date());
        wrapper.apply("{0} <= DATE_FORMAT(issuance_date,'%Y-%m-%d')", startDate);
        wrapper.apply("{0} >= DATE_FORMAT(issuance_date,'%Y-%m-%d')", endDate);
        wrapper.eq("approval_status", ApprovalStatusEnum.UN_DRAFT);
        Long certCount = certificateReportMapper.selectCount(wrapper);
        List<SampleStatusMonthResponse> resultList = new ArrayList<>();
        SampleStatusMonthResponse response1 = new SampleStatusMonthResponse();
        response1.setStatus("待收入");
        response1.setQuantity(dispatchVoPage.getTotal());
        SampleStatusMonthResponse response3 = new SampleStatusMonthResponse();
        response3.setStatus("检测中");
        response3.setQuantity(inList.getTotal());
        SampleStatusMonthResponse response4 = new SampleStatusMonthResponse();
        response4.setStatus("成编制报告");
        response4.setQuantity(certCount);
        resultList.add(response1);
        resultList.add(response2);
        resultList.add(response3);
        resultList.add(response4);
        return resultList;
    }

    private MeterStaff getMeterStaffInfo(AuthUser user) {
        String account = user.getAccount();
        QueryWrapper<MeterStaff> wrapper = new QueryWrapper<>();
        wrapper.eq("account", account);
        return staffMapper.selectOne(wrapper);
    }

    private Map<String, Object> selectDirectDept(AuthUser user) {
        Map<String, Object> resultMap = SqlRunner.db().selectOne(
                "SELECT su.DEPT_ID as deptId, sd.SIMPLE_NAME AS deptName FROM sys_role sr " +
                        "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " +
                        "JOIN sys_user su ON srr.USERID = su.ID " +
                        "JOIN sys_dept sd ON su.DEPT_ID = sd.ID " +
                        "WHERE su.ID = {0}" +
                        "AND sr.TIPS = {1}", String.valueOf(user.getId()), "director");
        return resultMap;
    }

}
