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.application.service.AbstractDictService;
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.FileApprovalListRequest;
import com.casic.missiles.dto.meter.FileApprovalListResponse;
import com.casic.missiles.dto.meter.FileListRequest;
import com.casic.missiles.dto.meter.FileSaveResponse;
import com.casic.missiles.enums.BusinessExceptionEnum;
import com.casic.missiles.enums.ExportEnum;
import com.casic.missiles.enums.meter.MeterDictEnum;
import com.casic.missiles.exception.BusinessException;
import com.casic.missiles.model.meter.MeterFile;
import com.casic.missiles.model.exception.enums.CoreExceptionEnum;
import com.casic.missiles.service.meter.IMeterFileService;
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.annotation.Resource;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 * @Description: 计量文件
 * 功能：
 * 1.列表、导出、保存至草稿、草稿编辑、文件更新为已废止、删除、批量删除
 * 2.文件提交
 * 根据表单id获取流程定义id；
 * 根据流程定义id启动流程实例，参考RuoYi，钉钉vue2中设置了几个流程变量，先不用
 * 3.文件审批
 * @Author: wangpeng
 * @Date: 2022/11/21 17:47
 */
@Api(tags = "计量文件管理接口")
@Controller
@RequestMapping("/meter/file")
public class MeterFileController extends ExportController {
    @Autowired
    private IMeterFileService meterFileService;
    @Resource
    private AbstractDictService dictService;

    /**
     * 文件列表，列表中查的是文件表中已通过的
     * 质量文件（计量法规、质量手册、程序文件、作业文件、技术能力、CNAS文件）、计量管理规章制度、计量管理办法、校准检测办法、计量规程
     */
    @ApiOperation("文件列表/详情（分页）")
    @PostMapping("/listPage")
    @ResponseBody
    public ReturnDTO<PageInfoBT<MeterFile>> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        Page<MeterFile> page = PageFactory.defaultPage();
        return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request)));
    }

    @ApiOperation("文件列表（不分页）")
    @PostMapping("/list")
    @ResponseBody
    public ReturnDTO<List<MeterFile>> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        return ReturnUtil.success(meterFileService.list(request));
    }

    @ApiOperation("文件导出")
    @PostMapping("/listExport")
    @ResponseBody
    public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException {
        if (bindingResult.hasErrors()) {
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        List<MeterFile> list;
        if (!CollectionUtils.isEmpty(request.getIds())) {
            list = meterFileService.listByIds(request.getIds());
            list.forEach(result -> {
                result.setApprovalStatusName(dictService.getDictNameByCode(MeterDictEnum.APPROVAL_STATUS, result.getApprovalStatus()));
                result.setEffectiveStatusName(dictService.getDictNameByCode(MeterDictEnum.EFFECTIVE_STATUS, result.getEffectiveStatus()));
                result.setFileTypeName(dictService.getDictNameByCode(MeterDictEnum.FILE_TYPE, result.getFileType()));
            });
        } else {
            list = meterFileService.list(request);
        }
        super.exportExcel(MeterFile.class, list, ExportEnum.FILE_EXPORT.getSheetName());
    }

    @ApiOperation("文件保存（保存至草稿箱）")
    @PostMapping("/save")
    @ResponseBody
    public ReturnDTO<FileSaveResponse> save(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        return meterFileService.saveFile(meterFile);
    }

    /**
     * 草稿箱文件编辑
     */
    @ApiOperation("草稿箱文件编辑")
    @PostMapping("/draftUpdate")
    @ResponseBody
    public ReturnDTO draftUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) {
        Assert.isFalse(Objects.isNull(meterFile.getId()), () -> {
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        });
        if (bindingResult.hasErrors()) {
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        return meterFileService.draftUpdate(meterFile);
    }

    /**
     * 文件提交前一定要保存至草稿箱，保证即使流程提交失败（也可在草稿箱中查看），提示用户“文件提交失败已保存至草稿箱，请在草稿箱中重新提交”
     * 提交的流程不会出现同一文件重复提交的情况，因为每次提交前会保存到草稿，且提交成功会更新为非草稿状态，不会出现待审批task关联同一业务主键
     */
    @ApiOperation("文件提交（未调用过保存接口保存至草稿箱需先调用保存接口，再调用该接口）")
    @PostMapping("/submit")
    @ResponseBody
    public ReturnDTO submit(@RequestBody @Valid BaseApprovalSubmitRequest request, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        return meterFileService.submitFile(request);
    }

    @ApiOperation("文件更新为已废止")
    @PostMapping("/update")
    @ResponseBody
    public ReturnDTO update(@RequestBody IdDTO idDTO) {
        Assert.isFalse(Objects.isNull(idDTO.getId()), () -> {
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        });
        return meterFileService.updateFile(idDTO.getId());
    }

    @ApiOperation("文件删除（草稿删除也调用该接口）")
    @PostMapping("/delete")
    @ResponseBody
    public ReturnDTO delete(@RequestBody @Valid IdDTO idDTO) {
        Assert.isFalse(Objects.isNull(idDTO.getId()), () -> {
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        });
        return meterFileService.deleteFile(idDTO.getId());
    }

    @ApiOperation("文件批量删除")
    @PostMapping("/batchDelete")
    @ResponseBody
    public ReturnDTO batchDelete(@RequestBody @Valid IdsDTO idsDTO) {
        Assert.isFalse(CollectionUtils.isEmpty(idsDTO.getIds()), () -> {
            throw new BusinessException(BusinessExceptionEnum.ID_NULL);
        });
        return meterFileService.deleteBatchFile(idsDTO.getIds());
    }

    /**
     * 文件审批，状态更新考虑要更新业务表状态和flowable的事务，每个状态的查询方式不同（每个状态列表对应的详情都需要查看流程的进行到哪,dingding有通过流程实例id查看详情（看原型图））
     * 全部：所有状态的单据
     * 草稿箱：发起者已保存，但未提交的单据
     * 待审批：流程到该审批者用户，用户要去审批的单据（采用activiti自己待办任务列表实现）
     * 审批中：管理员角色可以查看所有的未完成的任务（activiti查看所有待办任务列表实现），发起者可查看自己的（google工作流有收藏查看发起者自己的流程方法）
     * 已通过：管理员角色可以查看所有的，发起者可查看自己的，审批者可查看流程中有自己的（google工作流有收藏查看有参与的流程方法）
     * 未通过：管理员角色可以查看所有的，发起者可查看自己的，审批者可查看流程中有自己的且是自己审批过的，未走到的后续节点的审批人看不到
     * 已取消：管理员角色可以查看所有的，发起者可查看自己的，审批者无意义
     */
    @ApiOperation("文件审批列表及详情中基础信息（分页）")
    @PostMapping("/approval/listPage")
    @ResponseBody
    public ReturnDTO<PageInfoBT<FileApprovalListResponse>> approvalListPage(@RequestBody @Valid FileApprovalListRequest request, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage());
        }
        Page<FileApprovalListResponse> page = PageFactory.defaultPage();
        List<FileApprovalListResponse> responseList = meterFileService.approvalListPage(page, request);
        page.setRecords(responseList);
        return ReturnUtil.success(super.packForBT(page));
    }

    /**
     * 删除（发起者或具有删除权限的用户可以删除，已通过/未通过状态不可删除）
     * 前端控制按钮权限
     */
    @ApiOperation("审批操作-删除")
    @PostMapping("/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 meterFileService.approvalDelete(request);
    }

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

    @ApiOperation("用于选择下拉所依据的技术文件查询")
    @PostMapping("/querySelectList")
    @ResponseBody
    public ReturnDTO querySelectList()  {
        return meterFileService.querySelectList();
    }


}
