package com.casic.missiles.controller.meter;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.casic.missiles.core.base.controller.ExportController;
import com.casic.missiles.core.page.PageFactory;
import com.casic.missiles.core.page.PageInfoBT;
import com.casic.missiles.dto.*;
import com.casic.missiles.dto.flowable.ApprovalDeleteRequest;
import com.casic.missiles.dto.meter.*;
import com.casic.missiles.enums.BusinessExceptionEnum;
import com.casic.missiles.enums.ExportEnum;
import com.casic.missiles.exception.BusinessException;
import com.casic.missiles.model.meter.MeterTrainLog;
import com.casic.missiles.model.meter.MeterTrainPlan;
import com.casic.missiles.model.exception.enums.CoreExceptionEnum;
import com.casic.missiles.service.meter.IMeterTrainLogService;
import com.casic.missiles.service.meter.IMeterTrainPlanService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 * @Description: 培训管理
 * @Author: wangpeng
 * @Date: 2022/11/21 20:31
 */
@Api(tags = "培训管理接口")
@Controller
@RequestMapping("/meter/train")
public class MeterTrainController extends ExportController {
    @Autowired
    private IMeterTrainPlanService trainPlanService;
    @Autowired
    private IMeterTrainLogService trainLogService;

    @ApiOperation("培训计划列表（分页）")
    @PostMapping("/plan/listPage")
    @ResponseBody
    public ReturnDTO<PageInfoBT<MeterTrainPlan>> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        Page<MeterTrainPlan> page = PageFactory.defaultPage();
        return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request)));
    }

    @ApiOperation("培训计划列表")
    @PostMapping("/plan/list")
    @ResponseBody
    public ReturnDTO<List<MeterTrainPlan>> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        return ReturnUtil.success(trainPlanService.planList(request));
    }

    @ApiOperation("培训计划导出")
    @PostMapping("/plan/listExport")
    @ResponseBody
    public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException {
        if (bindingResult.hasErrors()) {
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        List<MeterTrainPlan> list;
        if (!CollectionUtils.isEmpty(request.getIds())) {
            list = trainPlanService.listByIds(request.getIds());
        } else {
            list = trainPlanService.planList(request);
        }
        super.exportExcel(MeterTrainPlan.class, list, ExportEnum.TRAIN_PLAN_EXPORT.getSheetName());
    }

    @ApiOperation("培训计划保存（保存至草稿箱）")
    @PostMapping("/plan/save")
    @ResponseBody
    public ReturnDTO<TrainPlanSaveResponse> save(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) {
        if(bindingResult.hasErrors()){
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        return trainPlanService.saveTrainPlan(trainPlan);
    }

    /**
     * 草稿箱计划编辑
     */
    @ApiOperation("草稿箱培训计划编辑")
    @PostMapping("/plan/draftUpdate")
    @ResponseBody
    public ReturnDTO draftUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) {
        Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> {
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        });
        if(bindingResult.hasErrors()){
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        return trainPlanService.draftUpdate(trainPlan);
    }

    @ApiOperation("培训计划提交（未调用过保存接口保存至草稿箱需先调用保存接口，再调用该接口）")
    @PostMapping("/plan/submit")
    @ResponseBody
    public ReturnDTO planSubmit(@RequestBody @Valid BaseApprovalSubmitRequest request, BindingResult bindingResult) {
        if(bindingResult.hasErrors()){
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        return trainPlanService.submitTrainPlan(request);
    }

//    @ApiOperation("培训计划更新（审批通过后还能更新？？暂时保留。。）")
    @PostMapping("/plan/update")
    @ResponseBody
    public ReturnDTO planUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) {
//        Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> {
//            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
//        });
//        Assert.isFalse(bindingResult.hasErrors(), () -> {
//            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
//        });
//        return trainPlanService.updateTrainPlan(trainPlan);
        return null;
    }

    @ApiOperation("培训计划删除（草稿删除也调用该接口）")
    @PostMapping("/plan/delete")
    @ResponseBody
    public ReturnDTO planDelete(@RequestBody @Valid IdDTO idDTO) {
        Assert.isFalse(Objects.isNull(idDTO.getId()), () -> {
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        });
        return trainPlanService.deleteTrainPlan(idDTO.getId());
    }

    @ApiOperation("培训计划批量删除")
    @PostMapping("/plan/batchDelete")
    @ResponseBody
    public ReturnDTO planBatchDelete(@RequestBody @Valid IdsDTO idsDTO) {
        Assert.isFalse(CollectionUtils.isEmpty(idsDTO.getIds()), () -> {
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        });
        return trainPlanService.deleteBatchTrainPlan(idsDTO.getIds());
    }

    @ApiOperation("培训计划详情")
    @PostMapping("/plan/detail")
    @ResponseBody
    public ReturnDTO<TrainPlanDetailResponse> planDetail(@RequestBody @Valid IdDTO idDTO) {
        Assert.isFalse(Objects.isNull(idDTO.getId()), () -> {
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        });
        return trainPlanService.trainPlanDetail(idDTO.getId());
    }

    //APP扫码后从培训计划详情中选择签到人员，扫码后提交调用签到接口，更新培训计划员工签到时间
    @ApiOperation("培训计划二维码")
    @PostMapping("/plan/qrCode")
    @ResponseBody
    public ReturnDTO<TrainPlanDetailResponse> planQrCode(@RequestBody @Valid IdDTO idDTO) {
        Assert.isFalse(Objects.isNull(idDTO.getId()), () -> {
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        });
        return trainPlanService.planQrCode(idDTO.getId());
    }

    @ApiOperation("签到（更新培训计划员工签到时间）")
    @PostMapping("/plan/signIn")
    @ResponseBody
    public ReturnDTO<TrainPlanDetailResponse> signIn(@RequestBody @Valid TrainPlanSignInRequest trainPlanSignInRequest, BindingResult bindingResult) {
        if(bindingResult.hasErrors()){
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        return trainPlanService.signIn(trainPlanSignInRequest);
    }

    @ApiOperation("培训计划审批列表及详情中基础信息（分页），培训学员情况可用培训计划详情接口")
    @PostMapping("/plan/approval/listPage")
    @ResponseBody
    public ReturnDTO<PageInfoBT<TrainPlanApprovalListResponse>> approvalListPage(@RequestBody @Valid TrainPlanApprovalListRequest request, BindingResult bindingResult) {
        if(bindingResult.hasErrors()){
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        Page<TrainPlanApprovalListResponse> page = PageFactory.defaultPage();
        List<TrainPlanApprovalListResponse> responseList = trainPlanService.approvalListPage(page, request);
        page.setRecords(responseList);
        return ReturnUtil.success(super.packForBT(page));
    }

    @ApiOperation("培训记录列表（分页）")
    @PostMapping("/log/listPage")
    @ResponseBody
    public ReturnDTO<PageInfoBT<MeterTrainLog>> logListPage(@RequestBody TrainLogListRequest request) {
        Page<MeterTrainLog> page = PageFactory.defaultPage();
        return ReturnUtil.success(super.packForBT(trainLogService.listPage(page, request)));
    }

    @ApiOperation("培训记录列表")
    @PostMapping("/log/list")
    @ResponseBody
    public ReturnDTO<List<MeterTrainLog>> logList(@RequestBody TrainLogListRequest request) {
        return ReturnUtil.success(trainLogService.logList(request));
    }

    @ApiOperation("培训记录导出")
    @PostMapping("/log/listExport")
    @ResponseBody
    public void export(@RequestBody TrainLogListRequest request) throws IOException {
        List<MeterTrainLog> list;
        if (!CollectionUtils.isEmpty(request.getIds())) {
            list = trainLogService.listByIds(request.getIds());
        } else {
            list = trainLogService.logList(request);
        }
        super.exportExcel(MeterTrainLog.class, list, ExportEnum.TRAIN_LOG_EXPORT.getSheetName());
    }

    @ApiOperation("培训记录新建")
    @PostMapping("/log/add")
    @ResponseBody
    public ReturnDTO logAdd(@RequestBody TrainLogAddRequest request) {
        Assert.isFalse(Objects.isNull(request.getPlanId()), () -> {
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        });
        Assert.isFalse(CollectionUtils.isEmpty(request.getTrainStaffList()), () -> {
            throw new BusinessException(BusinessExceptionEnum.TRAIN_STAFF_NULL);
        });
        return trainLogService.addTrainLog(request);
    }

    @ApiOperation("培训记录更新")
    @PostMapping("/log/update")
    @ResponseBody
    public ReturnDTO logUpdate(@RequestBody TrainLogUpdateRequest request) {
        Assert.isFalse(Objects.isNull(request.getId()), () -> {
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        });
        Assert.isFalse(CollectionUtils.isEmpty(request.getTrainStaffList()), () -> {
            throw new BusinessException(BusinessExceptionEnum.TRAIN_STAFF_NULL);
        });
        return trainLogService.updateTrainLog(request);
    }

    @ApiOperation("培训记录详情")
    @PostMapping("/log/detail")
    @ResponseBody
    public ReturnDTO<TrainLogDetailResponse> logDetail(@RequestBody @Valid IdDTO idDTO) {
        Assert.isFalse(Objects.isNull(idDTO.getId()), () -> {
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        });
        return trainLogService.trainLogDetail(idDTO.getId());
    }

    /**
     * 计量人员列表（可根据培训计划查询）,用培训计划详情接口即可
     * 培训记录中学员从培训计划中人员中选择
     */

    /**
     * 删除（发起者或具有删除权限的用户可以删除，已通过/未通过状态不可删除）
     * 前端控制按钮权限
     */
    @ApiOperation("审批操作-删除")
    @PostMapping("/plan/approval/operate/delete")
    @ResponseBody
    public ReturnDTO delete(@RequestBody @Valid ApprovalDeleteRequest request, BindingResult bindingResult) {
        if(bindingResult.hasErrors()){
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        return trainPlanService.approvalDelete(request);
    }

    /**
     * 审批操作-编辑
     *      驳回的流程放置在未通过列表中，实现进行编辑后自动审核通过发起人节点
     */
    @ApiOperation("未通过培训计划编辑（驳回后的培训计划重新编辑，仅未通过列表中的编辑按钮可调用）")
    @PostMapping("/failUpdate")
    @ResponseBody
    public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) {
        Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> {
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        });
        if (bindingResult.hasErrors()) {
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        return trainPlanService.failUpdate(trainPlan);
    }
}
