package com.qmth.sop.server.api;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qmth.boot.api.constant.ApiConstant;
import com.qmth.sop.business.bean.result.TBCrmResult;
import com.qmth.sop.business.bean.result.UserArchivesAllocationResult;
import com.qmth.sop.business.entity.TBCrm;
import com.qmth.sop.business.entity.TBService;
import com.qmth.sop.business.service.ServiceAnalyseService;
import com.qmth.sop.business.service.TBCrmService;
import com.qmth.sop.common.contant.SystemConstant;
import com.qmth.sop.common.util.Result;
import com.qmth.sop.common.util.ResultUtil;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 服务单元分析 控制器
 *
 * @author: shudonghui
 * @date: 2023-08-14 15:55:18
 * @version: 1.0
 * @email: shudonghui@qmth.com.cn
 * @Company: www.qmth.com.cn
 */
@Api(tags = "服务单元分析 Controller")
@RestController
@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/service/analyse")
public class ServiceAnalyseController {

    @Resource
    ServiceAnalyseService serviceAnalyseService;

    @Resource
    TBCrmService tbCrmService;

    //服务单元列表
    @ApiOperation(value = "服务单元列表接口")
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "服务单元列表", response = TBService.class)})
    public Result list(@ApiParam(value = "开始时间", required = true) @RequestParam Long startTime,
                       @ApiParam(value = "结束时间", required = true) @RequestParam Long endTime) {
        List<TBService> list = serviceAnalyseService.list(startTime, endTime);
        return ResultUtil.ok(list);
    }

    /**
     * 4.服务单元概览
     * ①项目执行进度=服务单元下已完成的派单（研究生派单下SOP已完结；教务处派单下已有完成的SOP，无在执行的SOP。可能存在教务处多个SOP之间空窗期导致数据的误差，这个指标允许少量误差存在）；
     * ②设备出库总量：当前服务单元下已出库且尚未入库的设备总量；
     * ③设备占用率：（设备出库总量÷正常设备总量）×100%；
     * ④在服务人员总数：在执行的SOP现场服务人员数量，包括助理工程师、实施工程师、区域协调人；
     * ⑤现场人员占用率：（在服务人员总数÷认证有效的在服务人员总数）×100%；
     * ⑥以上指标都不需提供【数据下钻】；
     */
    @ApiOperation(value = "服务单元概览接口")
    @RequestMapping(value = "/overview", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "服务单元概览", response = Map.class)})
    public Result overview(@ApiParam(value = "服务单元", required = true) @RequestParam Long serviceUnitId) {
        return ResultUtil.ok(serviceAnalyseService.overview(serviceUnitId));
    }

    /**
     * 5.人力供应商项目数量分布及占比：
     * ①当前服务单元已划分了区域协调人的项目总数、供应商分布占比；
     * ②派单数：可提供【数据下钻】，点击派单数后可显示该服务单元下已调配了区域协调人的派单项目明细；明细表需要增加“服务单元”、“供应商”字段；
     * ③供应商：点击供应商，显示当前供应商在该服务单元下的派单项目明细；明细表需要增加“服务单元”、“供应商”字段；
     */
    @ApiOperation(value = "人力供应商项目数量分布及占比")
    @RequestMapping(value = "/supplier", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "人力供应商项目数量分布及占比", response = Map.class)})
    public Result supplier(@ApiParam(value = "服务单元", required = true) @RequestParam Long serviceUnitId) {
        Map<String, Object> map = serviceAnalyseService.supplier(serviceUnitId);
        return ResultUtil.ok(map);
    }

    /**
     * ②派单数：可提供【数据下钻】，点击派单数后可显示该服务单元下已调配了区域协调人的派单项目明细；明细表需要增加“服务单元”、“供应商”字段；
     * ③供应商：点击供应商，显示当前供应商在该服务单元下的派单项目明细；明细表需要增加“服务单元”、“供应商”字段；
     */
    @ApiOperation(value = "派单明细")
    @RequestMapping(value = "/supplier/detail", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "派单明细", response = TBCrmResult.class)})
    public Result dispatch(@ApiParam(value = "服务单元", required = true) @RequestParam Long serviceUnitId,
                           @ApiParam(value = "供应商") @RequestParam(required = false) Long supplierId,
                           @ApiParam(value = "分页页码", required = true) @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
                           @ApiParam(value = "分页数", required = true) @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {
        IPage<TBCrmResult> resultIPage = serviceAnalyseService.supplierDetail(new Page<>(pageNumber, pageSize), serviceUnitId, supplierId);
        return ResultUtil.ok(resultIPage);
    }

    /**
     * 6.人力供应商项目角色人员分布：
     * ①默认选中当前服务单元下项目调配人数最多的人力供应商；
     * ②显示当前供应商提供的项目角色各自的人数占比；
     * ③覆盖大区：统计当前服务单元下该供应商区域协调人负责的项目覆盖的大区数量及明细；
     */
    @ApiOperation(value = "人力供应商项目角色人员分布")
    @RequestMapping(value = "/supplier/role", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "人力供应商项目角色人员分布", response = Map.class)})
    public Result role(
            @ApiParam(value = "服务单元", required = true) @RequestParam Long serviceUnitId,
            @ApiParam(value = "供应商", required = true) @RequestParam Long supplierId) {
        List<Map<String, Object>> list = serviceAnalyseService.supplierRole(serviceUnitId, supplierId);
        return ResultUtil.ok(list);
    }

    /**
     * * ③覆盖大区：统计当前服务单元下该供应商区域协调人负责的项目覆盖的大区数量及明细；
     */
    @ApiOperation(value = "人力供应商覆盖大区")
    @RequestMapping(value = "/supplier/region", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "人力供应商覆盖大区", response = Map.class)})
    public Result region(@ApiParam(value = "服务单元", required = true) @RequestParam Long serviceUnitId,
                         @ApiParam(value = "供应商", required = false) @RequestParam(required = false) Long supplierId) {
        List<Map<String, Object>> list = serviceAnalyseService.supplierRegion(serviceUnitId, supplierId);
        return ResultUtil.ok(list);
    }

    /**
     * 统计当前服务单元下该供应商区域协调人负责的项目覆盖的大区明细；
     */
    @ApiOperation(value = "人力供应商覆盖大区明细")
    @RequestMapping(value = "/supplier/region/detail", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "人力供应商覆盖大区", response = Map.class)})
    public Result regionDetail(@ApiParam(value = "服务单元", required = true) @RequestParam Long serviceUnitId,
                               @ApiParam(value = "供应商", required = true) @RequestParam Long supplierId,
                               @ApiParam(value = "大区", required = true) @RequestParam Long regionId) {
        Map<String, Object> map = new HashMap<>();
        map.put("projectRoleQuota", serviceAnalyseService.findCrmAllocationSubTotal(serviceUnitId, regionId, null));
//        List<UserArchivesAllocationResult> crmAllocation = serviceAnalyseService.findCrmAllocation(serviceUnitId, regionId, null);
//        map.put("projectWait", crmAllocation.stream().filter(e -> e.getDistributed() < e.getQuota()).count());
//        map.put("regionCities", crmAllocation.stream().filter(e -> e.getCity() != null).collect(Collectors.groupingBy(UserArchivesAllocationResult::getCity)).size());
        map.put("projectWait", serviceAnalyseService.findWaitZone(regionId));
        map.put("regionCities", tbCrmService.count(new QueryWrapper<TBCrm>().lambda().eq(TBCrm::getRegionId, regionId)));
        return ResultUtil.ok(map);
    }

    /**
     * 7.项目调配完成进度=（差额为0的派单总数÷派单总数）×100%；不提供【数据下钻】
     */
    @ApiOperation(value = "项目调配完成进度")
    @RequestMapping(value = "/project/allocation", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "项目调配完成进度", response = Double.class)})
    public Result allocation(@ApiParam(value = "服务单元", required = true) @RequestParam Long serviceUnitId) {
        List<UserArchivesAllocationResult> crmAllocation = serviceAnalyseService.findCrmAllocation(serviceUnitId, null, null);

        double result = crmAllocation.isEmpty() ? 0.00 : (double) crmAllocation.stream().filter(e -> e.getUnDistributed() == 0).count() / crmAllocation.size();
// 创建DecimalFormat对象，指定保留两位小数
        DecimalFormat decimalFormat = new DecimalFormat("#0.00");
// 使用DecimalFormat格式化浮点数结果，得到字符串形式的结果
        String formattedResult = decimalFormat.format(result);
// 输出格式化后的结果
        return ResultUtil.success(formattedResult);
    }

    /**
     * 8.人员配额完成进度=（已分配人员数量÷总配额）×100%；不提供【数据下钻】
     */
    @ApiOperation(value = "人员配额完成进度")
    @RequestMapping(value = "/personnel/quota", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "人员配额完成进度", response = Double.class)})
    public Result quota(@ApiParam(value = "服务单元", required = true) @RequestParam Long serviceUnitId) {
        List<UserArchivesAllocationResult> list = serviceAnalyseService.findCrmAllocation(serviceUnitId, null, null);
        int quota = list.stream().mapToInt(UserArchivesAllocationResult::getQuota).sum();
        int distributed = list.stream().mapToInt(UserArchivesAllocationResult::getDistributed).sum();
        double result = quota == 0 ? 0 : (double) distributed / quota;
// 创建DecimalFormat对象，指定保留两位小数
        DecimalFormat decimalFormat = new DecimalFormat("#0.00");
// 使用DecimalFormat格式化浮点数结果，得到字符串形式的结果
        String formattedResult = decimalFormat.format(result);
// 输出格式化后的结果
        return ResultUtil.success(formattedResult);
    }

    /**
     * 9.设备供应商设备使用占比：当前服务单元下各设备供应商提供已出库尚未出库的设备的数量及占比；
     */
    @ApiOperation(value = "设备供应商设备使用占比")
    @RequestMapping(value = "/device/use", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "设备供应商设备使用占比", response = Map.class)})
    public Result device(@ApiParam(value = "服务单元", required = true) @RequestParam Long serviceUnitId) {
        List<Map<String, Object>> list = serviceAnalyseService.device(serviceUnitId);
        return ResultUtil.ok(list);
    }

    /**
     * 10.大区服务人数分布及对比：
     * 1.当前服务单元下各大区在服务人员的数量分布及对比。单个柱形图可按供应商占比分颜色展示占比。
     * 2.在服务人员：发布的派单所占用的资源
     * 3.按照自小单元 大区-供应商 去重
     */
    @ApiOperation(value = "大区服务人数分布及对比")
    @RequestMapping(value = "/region/personnel", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "大区服务人数分布及对比", response = Map.class)})
    public Result personnel(@ApiParam(value = "服务单元", required = true) @RequestParam Long serviceUnitId) {
        return ResultUtil.ok(serviceAnalyseService.personnel(serviceUnitId));
    }
}