package cn.iocoder.yudao.module.pms.controller.admin.iotfivedailyreport;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.pms.controller.admin.iotfivedailyreport.vo.IotFiveDailyReportPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotfivedailyreport.vo.IotFiveDailyReportRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotfivedailyreport.vo.IotFiveDailyReportSaveReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotfivedailyreport.vo.IotFiveDailyReportStatisticsRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotprojectinfo.vo.IotProjectInfoPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttaskschedule.vo.IotProjectTaskSchedulePageReqVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotfivedailyreport.IotFiveDailyReportDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojectinfo.IotProjectInfoDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttask.IotProjectTaskDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttaskschedule.IotProjectTaskScheduleDO;
import cn.iocoder.yudao.module.pms.service.iotfivedailyreport.IotFiveDailyReportService;
import cn.iocoder.yudao.module.pms.service.iotprojectinfo.IotProjectInfoService;
import cn.iocoder.yudao.module.pms.service.iotprojecttask.IotProjectTaskService;
import cn.iocoder.yudao.module.pms.service.iotprojecttaskschedule.IotProjectTaskScheduleService;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dict.DictDataService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.*;

import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;

@Tag(name = "管理后台 - 5#国日报")
@RestController
@RequestMapping("/pms/iot-five-daily-report")
@Validated
public class IotFiveDailyReportController {

    @Resource
    private IotFiveDailyReportService iotFiveDailyReportService;
    @Resource
    private DeptService deptService;
    @Resource
    private IotProjectInfoService iotProjectInfoService;

    @Resource
    private IotProjectTaskService iotProjectTaskService;
    @Resource
    private DictDataService dictDataService;
    @Resource
    private IotProjectTaskScheduleService iotProjectTaskScheduleService;


    @PostMapping("/create")
    @Operation(summary = "创建5#国日报")
    @PreAuthorize("@ss.hasPermission('pms:iot-five-daily-report:create')")
    public CommonResult<Long> createIotFiveDailyReport(@Valid @RequestBody IotFiveDailyReportSaveReqVO createReqVO) {
        return success(iotFiveDailyReportService.createIotFiveDailyReport(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新5#国日报")
    @PreAuthorize("@ss.hasPermission('pms:iot-five-daily-report:update')")
    public CommonResult<Boolean> updateIotFiveDailyReport(@Valid @RequestBody IotFiveDailyReportSaveReqVO updateReqVO) {
        iotFiveDailyReportService.updateIotFiveDailyReport(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除5#国日报")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('pms:iot-five-daily-report:delete')")
    public CommonResult<Boolean> deleteIotFiveDailyReport(@RequestParam("id") Long id) {
        iotFiveDailyReportService.deleteIotFiveDailyReport(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得5#国日报")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('pms:iot-five-daily-report:query')")
    public CommonResult<IotFiveDailyReportRespVO> getIotFiveDailyReport(@RequestParam("id") Long id) {
        IotFiveDailyReportDO iotFiveDailyReport = iotFiveDailyReportService.getIotFiveDailyReport(id);
        return success(buildDailyReport(iotFiveDailyReport));
    }

    /**
     * 查询日报对应的项目 任务信息
     * @param dailyReport
     * @return
     */
    private IotFiveDailyReportRespVO buildDailyReport(IotFiveDailyReportDO dailyReport) {
        // 如果 dailyReport 为空 返回空对象 有可能任务中安排的人员部门 与日报所在部门不同
        if (ObjUtil.isEmpty(dailyReport)) {
            return new IotFiveDailyReportRespVO();
        }
        IotFiveDailyReportRespVO dailyReportVO = BeanUtils.toBean(dailyReport, IotFiveDailyReportRespVO.class);

        LocalDateTime reportTime = dailyReportVO.getCreateTime();
        // 当月计划工作量，默认0
        BigDecimal monthPlanLayers = BigDecimal.ZERO;

        // 设置 日报 的项目 任务 等信息
        // key施工状态数据字典value   value施工状态数据字典label
        Map<String, String> constructStatusPair = new HashMap<>();
        // 施工状态 字典数据
        List<DictDataDO> rdStatusData = dictDataService.getDictDataListByDictType("rdStatus");
        if (CollUtil.isNotEmpty(rdStatusData)) {
            rdStatusData.forEach(data -> {
                constructStatusPair.put(data.getValue(), data.getLabel());
            });
        }
        if (CollUtil.isNotEmpty(constructStatusPair)) {
            String statusLabel = constructStatusPair.get(dailyReportVO.getFiveStatus());
            dailyReportVO.setFiveStatusLabel(statusLabel);
        }
        // 当前日报的设备利用率 作业泵车数量 / 主设备泵车数量
        BigDecimal mainDeviceNum = dailyReportVO.getMainDeviceNum();
        BigDecimal wokDeviceNum = dailyReportVO.getWokDeviceNum();
        if (mainDeviceNum.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal utilizationRate = wokDeviceNum.divide(mainDeviceNum, 4, RoundingMode.HALF_UP );
            dailyReportVO.setUtilizationRate(utilizationRate);
        }
        // 当前日报的 施工队伍
        if (ObjUtil.isNotEmpty(dailyReportVO.getDeptId())) {
            DeptDO dept = deptService.getDept(dailyReportVO.getDeptId());
            if (ObjUtil.isNotEmpty(dept)) {
                dailyReportVO.setDeptName(dept.getName());
            }
        }
        // 当前日报的 项目信息
        if (ObjUtil.isNotEmpty(dailyReportVO.getProjectId())) {
            IotProjectInfoDO projectInfo = iotProjectInfoService.getIotProjectInfo(dailyReportVO.getProjectId());
            if (ObjUtil.isNotEmpty(projectInfo)) {
                dailyReportVO.setProjectName(projectInfo.getContractName());
                dailyReportVO.setCustomer(projectInfo.getManufactureName());
            }
        }
        // 查询当前日报关联的 任务信息
        if (ObjUtil.isNotEmpty(dailyReportVO.getTaskId())) {
            IotProjectTaskDO projectTask = iotProjectTaskService.getIotProjectTask(dailyReportVO.getTaskId());
            if (ObjUtil.isNotEmpty(projectTask)) {
                dailyReportVO.setLocation(projectTask.getLocation());
                dailyReportVO.setWellName(projectTask.getWellName());
            }
            // 查询当前日报施工队伍部门对应的 任务计划信息
            IotProjectTaskSchedulePageReqVO pageReqVO = new IotProjectTaskSchedulePageReqVO();
            pageReqVO.setTaskId(dailyReportVO.getTaskId());
            List<IotProjectTaskScheduleDO> taskSchedules = iotProjectTaskScheduleService.getIotProjectTaskSchedules(pageReqVO);
            if (CollUtil.isNotEmpty(taskSchedules) && ObjUtil.isNotEmpty(reportTime)) {
                // 获取日报所属年月
                YearMonth reportYearMonth = YearMonth.from(reportTime);
                // Stream过滤：计划开始时间年月 和 日报年月一致，累加planLayers
                monthPlanLayers = taskSchedules.stream()
                        // 过滤计划开始时间不为空，且年月匹配
                        .filter(schedule -> ObjUtil.isNotEmpty(schedule.getStartTime()))
                        .filter(schedule -> YearMonth.from(schedule.getStartTime()).equals(reportYearMonth))
                        // 提取计划层数，空值替换0
                        .map(schedule -> ObjUtil.defaultIfNull(schedule.getPlanLayers(), BigDecimal.ZERO))
                        // 累加求和
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
            }
        }
        // 赋值当月计划压裂层数
        dailyReportVO.setPlanWorkingLayers(monthPlanLayers);

        return dailyReportVO;
    }

    @GetMapping("/page")
    @Operation(summary = "获得5#国日报分页")
    @PreAuthorize("@ss.hasPermission('pms:iot-five-daily-report:query')")
    public CommonResult<PageResult<IotFiveDailyReportRespVO>> getIotFiveDailyReportPage(@Valid IotFiveDailyReportPageReqVO pageReqVO) {
        PageResult<IotFiveDailyReportDO> pageResult = iotFiveDailyReportService.getIotFiveDailyReportPage(pageReqVO);
        return success(new PageResult<>(buildDailyReportList(pageResult.getList()), pageResult.getTotal()));
    }

    /**
     * 设置日报的关联信息 部门(施工队伍) 项目 任务 带班干部 日报填报人
     * @param reports
     * @return
     */
    private List<IotFiveDailyReportRespVO> buildDailyReportList(List<IotFiveDailyReportDO> reports) {
        if (CollUtil.isEmpty(reports)) {
            return Collections.emptyList();
        }
        // key项目id   value项目合同号
        Map<Long, String> projectPair = new HashMap<>();
        // key项目id   value项目客户名称
        Map<Long, String> customerPair = new HashMap<>();
        //  key任务id     value任务井号
        Map<Long, String> taskPair = new HashMap<>();
        //  key任务id     value任务施工区域
        Map<Long, String> taskLocationPair = new HashMap<>();
        // key施工状态数据字典value   value施工状态数据字典label
        Map<String, String> constructStatusPair = new HashMap<>();
        //  key日报id     value日报设备利用率
        Map<Long, BigDecimal> reportRatePair = new HashMap<>();
        // 设备部门信息
        Map<Long, DeptDO> tempDeptMap = deptService.getDeptMap(convertList(reports, IotFiveDailyReportDO::getDeptId));
        // 施工状态 字典数据
        List<DictDataDO> rdStatusData = dictDataService.getDictDataListByDictType("rdStatus");
        if (CollUtil.isNotEmpty(rdStatusData)) {
            rdStatusData.forEach(data -> {
                constructStatusPair.put(data.getValue(), data.getLabel());
            });
        }
        // 计算每个日报的 设备利用率
        reports.forEach(report -> {
            // 设备利用率 作业泵车数量 / 主设备泵车数量
            BigDecimal mainDeviceNum = report.getMainDeviceNum();
            BigDecimal wokDeviceNum = report.getWokDeviceNum();
            if (mainDeviceNum.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal utilizationRate = wokDeviceNum.divide(mainDeviceNum, 4, RoundingMode.HALF_UP );
                reportRatePair.put(report.getId(), utilizationRate);
            }
        });
        DataPermissionUtils.executeIgnore(() -> {
            // 查询日报关联的项目信息
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setProjectIds(convertList(reports, IotFiveDailyReportDO::getProjectId));
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectPair.put(project.getId(), project.getContractName());
                    customerPair.put(project.getId(), project.getManufactureName());
                });
            }
            // 查询任务 井号 施工区域 信息
            IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
            taskReqVO.setTaskIds(convertList(reports, IotFiveDailyReportDO::getTaskId));
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskPair.put(task.getId(), task.getWellName());
                    taskLocationPair.put(task.getId(), task.getLocation());
                });
            }
        });
        return BeanUtils.toBean(reports, IotFiveDailyReportRespVO.class, (reportVO) -> {
            // 施工状态 导出使用
            if (StrUtil.isNotBlank(reportVO.getFiveStatus())) {
                if (constructStatusPair.containsKey(reportVO.getFiveStatus())) {
                    reportVO.setFiveStatusLabel(constructStatusPair.get(reportVO.getFiveStatus()));
                }
            }
            // 日报的 设备利用率
            findAndThen(reportRatePair, reportVO.getId(), utilizationRate -> reportVO.setUtilizationRate(utilizationRate));
            // 日报的 施工队伍
            findAndThen(tempDeptMap, reportVO.getDeptId(), dept -> reportVO.setDeptName(dept.getName()));
            // 日报关联的项目信息
            findAndThen(projectPair, reportVO.getProjectId(), contractName -> reportVO.setProjectName(contractName));
            // 日报关联的项目客户信息
            findAndThen(customerPair, reportVO.getProjectId(), customerName -> reportVO.setCustomer(customerName));
            // 日报关联的任务井号
            findAndThen(taskPair, reportVO.getTaskId(), taskName -> reportVO.setWellName(taskName));
            // 日报关联的任务施工区域
            findAndThen(taskLocationPair, reportVO.getTaskId(), location -> reportVO.setLocation(location));
        });
    }

    @GetMapping("/totalWorkload")
    @Operation(summary = "5#国日报 汇总 统计 卡片")
    @PreAuthorize("@ss.hasPermission('pms:iot-five-daily-report:query')")
    public CommonResult<IotFiveDailyReportStatisticsRespVO> totalWorkload(@Valid IotFiveDailyReportPageReqVO pageReqVO) {
        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
        Set<Long> projectIds = new HashSet<>();
        Set<Long> taskIds = new HashSet<>();
        if (StrUtil.isNotBlank(pageReqVO.getProjectName())) {
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setContractName(pageReqVO.getProjectName());
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectIds.add(project.getId());
                });
                pageReqVO.setProjectIds(projectIds);
            }
        }
        if (StrUtil.isNotBlank(pageReqVO.getWellName())) {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setSearchKey(pageReqVO.getWellName());
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
                pageReqVO.setTaskIds(taskIds);
            }
        }
        IotFiveDailyReportStatisticsRespVO statistics = iotFiveDailyReportService.totalWorkload(pageReqVO);
        return success(statistics);
    }

    @GetMapping("/summaryStatistics")
    @Operation(summary = "5#国日报 汇总 统计")
    @PreAuthorize("@ss.hasPermission('pms:iot-five-daily-report:query')")
    public CommonResult<Map<String, Object>> summaryStatistics(@Valid IotFiveDailyReportPageReqVO pageReqVO) {
        List<IotFiveDailyReportStatisticsRespVO> result = new ArrayList<>();
        Map<String, Object> resultMap = new HashMap<>();
        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
        Set<Long> projectIds = new HashSet<>();
        Set<Long> taskIds = new HashSet<>();
        if (StrUtil.isNotBlank(pageReqVO.getProjectName())) {
            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
            reqVO.setContractName(pageReqVO.getProjectName());
            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
            if (CollUtil.isNotEmpty(projects)) {
                projects.forEach(project -> {
                    projectIds.add(project.getId());
                });
                pageReqVO.setProjectIds(projectIds);
            }
        }
        if (StrUtil.isNotBlank(pageReqVO.getWellName())) {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setSearchKey(pageReqVO.getWellName());
            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
            if (CollUtil.isNotEmpty(tasks)) {
                tasks.forEach(task -> {
                    taskIds.add(task.getId());
                });
                pageReqVO.setTaskIds(taskIds);
            }
        }
        List<IotFiveDailyReportStatisticsRespVO> statistics = iotFiveDailyReportService.summaryStatistics(pageReqVO);
        result.addAll(statistics);
        resultMap.put("list", result);
        resultMap.put("total", result.size());
        return success(resultMap);
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出5#国日报 Excel")
    @PreAuthorize("@ss.hasPermission('pms:iot-five-daily-report:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportIotFiveDailyReportExcel(@Valid IotFiveDailyReportPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<IotFiveDailyReportDO> list = iotFiveDailyReportService.getIotFiveDailyReportPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "5#国日报.xls", "数据", IotFiveDailyReportRespVO.class,
                        BeanUtils.toBean(list, IotFiveDailyReportRespVO.class));
    }

}