package com.qmth.sop.server.api;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.entity.*;
import com.qmth.sop.common.annotation.OperationLog;
import com.qmth.sop.business.bean.params.DingSaveParam;
import com.qmth.sop.business.bean.result.*;
import com.qmth.sop.business.service.*;
import com.qmth.sop.business.templete.execute.AsyncDingCountExportService;
import com.qmth.sop.common.contant.SystemConstant;
import com.qmth.sop.common.enums.*;
import com.qmth.sop.common.util.Result;
import com.qmth.sop.common.util.ResultUtil;
import com.qmth.sop.common.util.ServletUtil;
import io.swagger.annotations.*;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 考勤打卡表 控制器
 *
 * @author: shudonghui
 * @date: 2023-08-10 14:23:08
 * @version: 1.0
 * @email: shudonghui@qmth.com.cn
 * @Company: www.qmth.com.cn
 */
@Api(tags = "考勤打卡表 Controller")
@RestController
@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + SystemConstant.PREFIX_URL_DING)
public class TBDingController {
    @Resource
    TBDingService tBDingService;

    @Resource
    TBTaskService tbTaskService;
    @Resource
    AsyncDingCountExportService asyncDingCountExportService;

    @Resource
    TBSopInfoService tbSopInfoService;

    @Resource
    TBCrmService tbCrmService;

    @Resource
    TBServiceService tbServiceService;


    @ApiOperation(value = "考勤明细")
    @RequestMapping(value = "/detail", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = TBDing.class)})
    public Result detail(@ApiParam(value = "sop单号", required = true) @RequestParam String sopNo,
                         @ApiParam(value = "人员档案id", required = true) @RequestParam Long archivesId,
                         @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) {
        return ResultUtil.ok(tBDingService.page(new Page<>(pageNumber, pageSize), new LambdaQueryWrapper<>(new TBDing()).eq(TBDing::getSopNo, sopNo).eq(TBDing::getUserArchivesId, archivesId)));
    }

    @ApiOperation(value = "工时统计统计查询接口")
    @RequestMapping(value = "/query", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "工时统计统计查询结果", response = TBDingSubmitQueryResult.class)})
    public Result query(
            @ApiParam(value = "服务单元", required = false) @RequestParam(required = false) Long serviceId,
            @ApiParam(value = "提交状态", required = false) @RequestParam(required = false) DingSubmitStatusEnum status,
            @ApiParam(value = "提交人", required = false) @RequestParam(required = false) Long submitUserId,
            @ApiParam(value = "姓名（模糊查询）", required = false) @RequestParam(required = false) String userName,
            @ApiParam(value = "供应商", required = false) @RequestParam(required = false) Long supplierId,
            @ApiParam(value = "客户名称（模糊查询）", required = false) @RequestParam(required = false) String custom,
            @ApiParam(value = "SOP流水号（模糊查询）", required = false) @RequestParam(required = false) String sopNo,
            @ApiParam(value = "违规工时", required = false) @RequestParam(required = false) Long days,
            @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<TBDingSubmitQueryResult> resultIPage = tBDingService.query(new Page<>(pageNumber, pageSize), serviceId, Objects.nonNull(status) ? status.name() : "", submitUserId, userName, supplierId, custom, sopNo, days);

        return ResultUtil.ok(resultIPage);
    }

    @ApiOperation(value = "工时统计统计接口")
    @RequestMapping(value = "/count", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "工时统计统计结果", response = TBDingCountResult.class)})
    public Result count(@ApiParam(value = "服务单元", required = false) @RequestParam(required = false) Long serviceId,
                        @ApiParam(value = "提交人", required = false) @RequestParam(required = false) Long createId,
                        @ApiParam(value = "姓名（模糊查询）", required = false) @RequestParam(required = false) String userName,
                        @ApiParam(value = "供应商", required = false) @RequestParam(required = false) Long supplierId,
                        @ApiParam(value = "客户名称（模糊查询）", required = false) @RequestParam(required = false) String custom,
                        @ApiParam(value = "SOP流水号（模糊查询）", required = false) @RequestParam(required = false) String sopNo
    ) {
        TBDingCountResult result = tBDingService.count(serviceId, createId, userName, supplierId, custom, sopNo);

        return ResultUtil.ok(result);
    }


    @ApiOperation(value = "工时统计导出")
    @RequestMapping(value = "/export", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
    @OperationLog(logType = LogTypeEnum.EXPORT)
    public Result export(@ApiParam(value = "服务单元", required = false) @RequestParam(required = false) Long serviceId,
                         @ApiParam(value = "提交状态", required = false) @RequestParam(required = false) String status,
                         @ApiParam(value = "提交人", required = false) @RequestParam(required = false) Long createId,
                         @ApiParam(value = "姓名（模糊查询）", required = false) @RequestParam(required = false) String userName,
                         @ApiParam(value = "供应商", required = false) @RequestParam(required = false) Long supplierId,
                         @ApiParam(value = "客户名称（模糊查询）", required = false) @RequestParam(required = false) String custom,
                         @ApiParam(value = "SOP流水号（模糊查询）", required = false) @RequestParam(required = false) String sopNo,
                         @ApiParam(value = "违规工时", required = false) @RequestParam(required = false) Long days) throws Exception {
        Map<String, Object> map = tbTaskService.saveTask(TaskTypeEnum.DING_COUNT_EXPORT);
        map.putIfAbsent("serviceId", serviceId);
        map.putIfAbsent("status", status);
        map.putIfAbsent("createId", createId);
        map.putIfAbsent("userName", userName);
        map.putIfAbsent("supplierId", supplierId);
        map.putIfAbsent("custom", custom);
        map.putIfAbsent("sopNo", sopNo);
        map.putIfAbsent("days", days);
        asyncDingCountExportService.exportTask(map);
        TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
        return ResultUtil.ok(tbTask.getId());
    }


    @ApiOperation(value = "考勤明细查询接口")
    @RequestMapping(value = "/attendance/query", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "考勤明细查询结果", response = TBDingAttendanceResult.class)})
    public Result attendanceQuery(
            @ApiParam(value = "服务单元", required = false) @RequestParam(required = false) Long serviceId,
            @ApiParam(value = "姓名（模糊查询）", required = false) @RequestParam(required = false) String userName,
            @ApiParam(value = "考勤日期开始", required = false) @RequestParam(required = false) Long startTime,
            @ApiParam(value = "考勤日期结束", required = false) @RequestParam(required = false) Long endTime,
            @ApiParam(value = "供应商", required = false) @RequestParam(required = false) Long supplierId,
            @ApiParam(value = "客户名称（模糊查询）", required = false) @RequestParam(required = false) String custom,
            @ApiParam(value = "SOP流水号（模糊查询）", required = false) @RequestParam(required = false) String sopNo,
            @ApiParam(value = "考勤类型", required = false) @RequestParam(required = false) InOutTypeEnum type,
            @ApiParam(value = "考勤结果", required = false) @RequestParam(required = false) DingResultEnum status,
            @ApiParam(value = "考勤异常数", required = false) @RequestParam(required = false) Long abnormal,
            @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<TBDingAttendanceResult> resultIPage = tBDingService.attendanceQuery(new Page<>(pageNumber, pageSize), serviceId, userName, startTime, endTime, supplierId, custom, sopNo, type, status, abnormal);

        return ResultUtil.ok(resultIPage);
    }


    @ApiOperation(value = "考勤明细统计接口")
    @RequestMapping(value = "/attendance/count", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "考勤明细统计结果", response = TBDingAttendanceCountResult.class)})
    public Result attendanceCount(@ApiParam(value = "服务单元", required = false) @RequestParam(required = false) Long serviceId,
                                  @ApiParam(value = "姓名（模糊查询）", required = false) @RequestParam(required = false) String userName,
                                  @ApiParam(value = "考勤日期开始", required = false) @RequestParam(required = false) Long startTime,
                                  @ApiParam(value = "考勤日期结束", required = false) @RequestParam(required = false) Long endTime,
                                  @ApiParam(value = "供应商", required = false) @RequestParam(required = false) Long supplierId,
                                  @ApiParam(value = "客户名称（模糊查询）", required = false) @RequestParam(required = false) String custom,
                                  @ApiParam(value = "SOP流水号（模糊查询）", required = false) @RequestParam(required = false) String sopNo
    ) {
        TBDingAttendanceCountResult result = tBDingService.attendanceCount(serviceId, userName, startTime, endTime, supplierId, custom, sopNo);

        return ResultUtil.ok(result);
    }


//    @ApiOperation(value = "考勤明细导出")
//    @RequestMapping(value = "/attendance/export", method = RequestMethod.POST)
//    @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
//    public Result attendanceExport(@ApiParam(value = "服务单元", required = false) @RequestParam(required = false) Long serviceId,
//                                   @ApiParam(value = "姓名（模糊查询）", required = false) @RequestParam(required = false) String userName,
//                                   @ApiParam(value = "考勤日期开始", required = false) @RequestParam(required = false) Long startTime,
//                                   @ApiParam(value = "考勤日期结束", required = false) @RequestParam(required = false) Long endTime,
//                                   @ApiParam(value = "供应商", required = false) @RequestParam(required = false) Long supplierId,
//                                   @ApiParam(value = "客户名称（模糊查询）", required = false) @RequestParam(required = false) String custom,
//                                   @ApiParam(value = "SOP流水号（模糊查询）", required = false) @RequestParam(required = false) String sopNo,
//                                   @ApiParam(value = "考勤类型", required = false) @RequestParam(required = false) String type,
//                                   @ApiParam(value = "考勤结果", required = false) @RequestParam(required = false) String status,
//                                   @ApiParam(value = "考勤异常数", required = false) @RequestParam(required = false) Long abnormal) throws Exception {
//        Map<String, Object> map = tbTaskService.saveTask(TaskTypeEnum.DING_ATTENDANCE_EXPORT);
//        map.putIfAbsent("serviceId", serviceId);
//        map.putIfAbsent("userName", userName);
//        map.putIfAbsent("startTime", startTime);
//        map.putIfAbsent("endTime", endTime);
//        map.putIfAbsent("supplierId", supplierId);
//        map.putIfAbsent("custom", custom);
//        map.putIfAbsent("sopNo", sopNo);
//        map.putIfAbsent("type", type);
//        map.putIfAbsent("status", status);
//        asyncDingAttendanceExportService.exportTask(map);
//        TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
//        return ResultUtil.ok(tbTask.getId());
//    }

    @ApiOperation(value = "考勤打卡信息")
    @RequestMapping(value = "/ding_info", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = DingElementResult.class)})
    public Result findDingInfo(@ApiParam(value = "sop单号", required = true) @RequestParam String sopNo) {
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        return ResultUtil.ok(tBDingService.findDingElements(sopNo, requestUser.getId()));
    }

    @ApiOperation(value = "考勤结果统计")
    @RequestMapping(value = "/ding_statistic", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = DingStatisticResult.class)})
    public Result findDingStatistic(@ApiParam(value = "sop单号", required = true) @RequestParam String sopNo) {
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        return ResultUtil.ok(tBDingService.findDingStatistic(sopNo, requestUser.getId()));
    }

    @ApiOperation(value = "考勤打卡保存")
    @RequestMapping(value = "/ding_save", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "更新成功", response = Result.class)})
    @OperationLog(logType = LogTypeEnum.UN_KNOW)
    public Result dingSave(@Valid @RequestBody DingSaveParam dingSaveParam, BindingResult bindingResult) throws IOException {
        if (bindingResult.hasErrors()) {
            return ResultUtil.error(bindingResult.getAllErrors().get(0).getDefaultMessage());
        }
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        tBDingService.dingSave(dingSaveParam, requestUser.getId());
        return ResultUtil.ok();
    }

    @ApiOperation(value = "考勤打卡-查询进行中的sop")
    @RequestMapping(value = "/ding_find_running_sop", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = DingElementResult.class)})
    public Result findDingRunningSop() {
        List<DingSopInfo> resultList = new ArrayList<>();
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        Long requestUserId = requestUser.getId();

        List<TBCrm> tbCrmList = tbCrmService.findAllCrm(requestUserId, null);
        if (CollectionUtils.isNotEmpty(tbCrmList)) {
            List<Long> serviceUnitIdList = tbCrmList.stream()
                    .map(TBCrm::getServiceId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());

            for (Long serviceUnitId : serviceUnitIdList) {
                DingSopInfo cell = new DingSopInfo();
                TBService service = tbServiceService.getById(serviceUnitId);
                if (Objects.isNull(service)) {
                    throw ExceptionResultEnum.ERROR.exception("未找到服务单元");
                }
                cell.setServiceUnitId(serviceUnitId);
                cell.setServiceUnitName(service.getName());
                List<TBCrm> crmInServiceList = tbCrmList.stream()
                        .filter(e -> serviceUnitId.equals(e.getServiceId()))
                        .distinct()
                        .collect(Collectors.toList());
                for (TBCrm tbCrm : crmInServiceList) {
                    CrmProjectResult crmProjectResult = tbCrmService.findCrmProjectBySopNoOrCrmNo(null, tbCrm.getCrmNo());
                    List<String> sopNoList = tbSopInfoService.findFlowPassageByCrmNo(tbCrm.getCrmNo(), requestUserId);
                    if (CollectionUtils.isEmpty(sopNoList)){
                        continue;
                    }
                    List<SopInfoResult> sopInfo = new ArrayList<>();
                    for (String sopNo : sopNoList) {
                        SopInfoResult result = new SopInfoResult();
                        result.setSopNo(sopNo);
                        result.setCrmNo(tbCrm.getCrmNo());
                        result.setCrmName(tbCrm.getName());
                        result.setCustomId(crmProjectResult.getCustomId());
                        result.setCustomName(crmProjectResult.getCustomName());
                        ProductTypeEnum productTypeEnum = crmProjectResult.getCustomType();
                        if (Objects.nonNull(productTypeEnum)) {
                            result.setCustomType(productTypeEnum);
                            result.setCustomTypeStr(crmProjectResult.getCustomType().getTitle());
                        }
                        sopInfo.add(result);
                    }
                    if (CollectionUtils.isNotEmpty(sopInfo)){
                        cell.setSopInfo(sopInfo);
                    }
                }
                if (CollectionUtils.isNotEmpty(cell.getSopInfo())){
                    resultList.add(cell);
                }
            }
        }
        return ResultUtil.ok(resultList);
    }

    @ApiOperation(value = "考勤打卡-查询所有sop")
    @RequestMapping(value = "/ding_find_all_sop", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = DingElementResult.class)})
    public Result findDingAllSop() {
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        List<DingSopInfo> resultList = new ArrayList<>();
        List<SopInfoResult> list = tbSopInfoService.findFlowByServiceId(null, requestUser.getId());
        List<Long> serviceUnitIdList = list.stream().map(SopInfoResult::getServiceId).distinct().collect(Collectors.toList());
        for (Long serviceUnitId : serviceUnitIdList) {
            DingSopInfo cell = new DingSopInfo();
            TBService service = tbServiceService.getById(serviceUnitId);
            if (Objects.isNull(service)) {
                throw ExceptionResultEnum.ERROR.exception("未找到服务单元");
            }

            cell.setServiceUnitId(serviceUnitId);
            cell.setServiceUnitName(service.getName());
            List<SopInfoResult> sopInServiceList = list.stream()
                    .filter(e -> serviceUnitId.equals(e.getServiceId()))
                    .distinct().collect(Collectors.toList());
            cell.setSopInfo(sopInServiceList);
            resultList.add(cell);
        }
        return ResultUtil.ok(resultList);
    }
}