package com.xjrsoft.module.material.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xjrsoft.common.model.result.R;
import com.xjrsoft.common.model.result.RT;
import com.xjrsoft.common.page.ConventPage;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.utils.VoToColumnUtil;
import com.xjrsoft.module.app.dto.UpdateEnableMarkDto;
import com.xjrsoft.module.form.dto.FormExecuteInfoDto;
import com.xjrsoft.module.form.service.IFormExecuteService;
import com.xjrsoft.module.material.dto.*;
import com.xjrsoft.module.material.entity.*;
import com.xjrsoft.module.material.service.IMaterialTaskAppendixService;
import com.xjrsoft.module.material.service.IMaterialTaskAssignService;
import com.xjrsoft.module.material.service.IMaterialTaskService;
import com.xjrsoft.module.material.vo.MaterialTaskAppendixVo;
import com.xjrsoft.module.material.vo.MaterialTaskAssignListVo;
import com.xjrsoft.module.material.vo.MaterialTaskAssignVo;
import com.xjrsoft.module.material.vo.MaterialTaskPageVo;
import com.xjrsoft.module.material.vo.MaterialTaskVo;
import com.xjrsoft.module.material.vo.MaterialTaskWaitPageVo;
import com.xjrsoft.module.organization.entity.Department;
import com.xjrsoft.module.organization.entity.UserDeptRelation;
import com.xjrsoft.module.personnel.entity.FaceIdentifyRecords;
import com.xjrsoft.module.system.entity.File;
import com.xjrsoft.module.teacher.entity.XjrUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
* @title: 材料提交任务
* @Author baicai
* @Date: 2023-10-31
* @Version 1.0
*/
@RestController
@RequestMapping("/material" + "/materialtask")
@Api(value = "/material"  + "/materialtask",tags = "材料提交任务代码")
@AllArgsConstructor
public class MaterialTaskController {
    private final IMaterialTaskService materialTaskService;

    private final IMaterialTaskAssignService materialTaskAssignService;

    private final IFormExecuteService formExecuteService;

    @GetMapping(value = "/page")
    @ApiOperation(value = "材料提交任务列表(分页 我发布的)")
    @SaCheckPermission("materialtask:detail")
    public RT<PageOutput<MaterialTaskPageVo>> page(@Valid MaterialTaskPageDto dto) {

        MPJLambdaWrapper<MaterialTask> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper
                .orderByDesc(MaterialTask::getId)
                .eq(MaterialTask::getCreateUserId, StpUtil.getLoginIdAsLong())
                .like(StrUtil.isNotBlank(dto.getName()), MaterialTask::getName, dto.getName())
                .eq((ObjectUtil.isNotEmpty(dto.getMaterialTypeId())) && dto.getMaterialTypeId() > 0, MaterialTask::getMaterialTypeId, dto.getMaterialTypeId())
                .eq((ObjectUtil.isNotEmpty(dto.getStatus())) && dto.getStatus() > 0, MaterialTask::getStatus, dto.getStatus())
                .gt(dto.getCreateDateStart() != null && !dto.getCreateDateStart().equals(""), MaterialTask::getCreateDate, dto.getCreateDateStart())
                .lt(dto.getCreateDateEnd() != null && !dto.getCreateDateEnd().equals(""), MaterialTask::getCreateDate, dto.getCreateDateEnd())
                .select(MaterialTask::getId)
                .selectAs(MaterialType::getName, MaterialTaskPageVo::getMaterialTypeIdCn)
                .selectAs(MaterialType::getCreateDate, MaterialTaskPageVo::getCreateDate)
                .select(MaterialTask.class, x -> VoToColumnUtil.fieldsToColumns(MaterialTaskPageVo.class).contains(x.getProperty()))
                .leftJoin(MaterialType.class, MaterialType::getId, MaterialTask::getMaterialTypeId);
        IPage<MaterialTaskPageVo> page = materialTaskService.selectJoinListPage(ConventPage.getPage(dto), MaterialTaskPageVo.class, queryWrapper);
        PageOutput<MaterialTaskPageVo> pageOutput = ConventPage.getPageOutput(page, MaterialTaskPageVo.class);
        return RT.ok(pageOutput);
    }

    @GetMapping(value = "/wait-page")
    @ApiOperation(value = "材料提交任务列表(分页 我的待办)")
    @SaCheckPermission("materialtask:detail")
    public RT<PageOutput<MaterialTaskWaitPageVo>> waitPage(@Valid MaterialTaskWaitPageDto dto) {

        MPJLambdaWrapper<MaterialTask> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper
                .disableLogicDel()
//                .eq(MaterialTask::getCreateUserId, StpUtil.getLoginIdAsLong())
                .like(StrUtil.isNotBlank(dto.getName()), MaterialTask::getName, dto.getName())
                .like(StrUtil.isNotBlank(dto.getAssignedUser()), XjrUser::getName, dto.getAssignedUser())
                .eq(ObjectUtil.isNotEmpty(dto.getStatus()), MaterialTask::getStatus, dto.getStatus())
//                .eq((ObjectUtil.isNotEmpty(dto.getMaterialTypeId())) && dto.getMaterialTypeId() > 0, MaterialTask::getMaterialTypeId, dto.getMaterialTypeId())
                .eq((dto.getExtStatus() != null && dto.getExtStatus() != 1), MaterialTaskAssign::getStatus, dto.getExtStatus())
                .and((dto.getExtStatus() != null && dto.getExtStatus() == 1),wp -> wp.eq(MaterialTaskAssign::getStatus, 1)
                        .or()
                        .eq(MaterialTaskAssign::getStatus, 4))
                .select(MaterialTask::getId)
                .select(MaterialTask.class, x -> VoToColumnUtil.fieldsToColumns(MaterialTaskWaitPageVo.class).contains(x.getProperty()))
                .innerJoin(MaterialTaskAssign.class, MaterialTaskAssign::getMaterialTaskId, MaterialTask::getId, ext -> ext.eq(MaterialTaskAssign::getUserId, StpUtil.getLoginIdAsLong()))
                .selectAs(MaterialTaskAssign::getId, MaterialTaskWaitPageVo::getAssignId)
                .selectAs(MaterialTaskAssign::getExecutiveStatus, MaterialTaskWaitPageVo::getExecutiveStatus)
                .selectAs(MaterialTaskAssign::getTransferAssignPerson, MaterialTaskWaitPageVo::getTransferAssignPerson)
                .selectAs(MaterialTaskAssign::getTransferSubmitedPerson, MaterialTaskWaitPageVo::getTransferSubmitedPerson)
                .selectAs(MaterialTaskAssign::getStatus, MaterialTaskWaitPageVo::getProcessStatus)
                .leftJoin(XjrUser.class, XjrUser::getId, MaterialTask::getCreateUserId, ext -> ext.selectAs(XjrUser::getName, MaterialTaskWaitPageVo::getCreateUserName))
                .leftJoin(MaterialTaskAppendix.class, MaterialTaskAppendix::getMaterialTaskId, MaterialTaskAssign::getId, ext -> ext.selectAs(MaterialTaskAppendix::getFileId, MaterialTaskWaitPageVo::getMaterialId))
        ;

//        if (ObjectUtil.isNotNull(dto.getRequiredCompleteStareTime()) && ObjectUtil.isNotNull(dto.getRequiredCompleteEndTime())) {
//            queryWrapper.ge(FaceIdentifyRecords::getVerifyTime, dto.getRequiredCompleteStareTime());
//            queryWrapper.le(FaceIdentifyRecords::getVerifyTime, dto.getRequiredCompleteEndTime());
//        }

        IPage<MaterialTaskWaitPageVo> page = materialTaskService.selectJoinListPage(ConventPage.getPage(dto), MaterialTaskWaitPageVo.class, queryWrapper);

        PageOutput<MaterialTaskWaitPageVo> pageOutput = ConventPage.getPageOutput(page);
        return RT.ok(pageOutput);
    }

    @GetMapping(value = "/info")
    @ApiOperation(value = "根据id查询材料提交任务信息")
    @SaCheckPermission("materialtask:detail")
    public RT<MaterialTaskVo> info(@RequestParam Long id) {
        MaterialTaskVo materialTaskVo = materialTaskService.getInfoById(id);
        return RT.ok(materialTaskVo);
    }


    @PostMapping
    @ApiOperation(value = "新增材料提交任务")
    @SaCheckPermission("materialtask:add")
    public RT<Long> add(@Valid @RequestBody AddMaterialTaskDto dto) {
        Long materialTaskId = materialTaskService.add(dto);
        //当返回了id表示成功添加了且需要发送通知
        if(materialTaskId != null && materialTaskId > 0 && dto.getSendMessage() != null && dto.getSendMessage() == 1){;
            materialTaskService.sendMessage(materialTaskId);
        }

        return RT.ok(materialTaskId);
    }

    @PutMapping
    @ApiOperation(value = "修改材料提交任务")
    @SaCheckPermission("materialtask:edit")
    public RT<Boolean> update(@Valid @RequestBody UpdateMaterialTaskDto dto) {

        MaterialTask materialTask = BeanUtil.toBean(dto, MaterialTask.class);
        return RT.ok(materialTaskService.update(materialTask));

    }

    @DeleteMapping
    @ApiOperation(value = "删除材料提交任务")
    @SaCheckPermission("materialtask:delete")
    public RT<Boolean> delete(@Valid @RequestBody List<Long> ids) {
        return RT.ok(materialTaskService.delete(ids));

    }

    @PostMapping("/import")
    @ApiOperation(value = "导入")
    public RT<Boolean> importData(@RequestParam MultipartFile file) throws IOException {
        List<MaterialTaskPageVo> savedDataList = EasyExcel.read(file.getInputStream()).head(MaterialTaskPageVo.class).sheet().doReadSync();
        Boolean result = materialTaskService.saveBatch(BeanUtil.copyToList(savedDataList, MaterialTask.class));
        return RT.ok(result);
    }

    @GetMapping("/export")
    @ApiOperation(value = "导出")
    public ResponseEntity<byte[]> exportData(@Valid MaterialTaskPageDto dto, @RequestParam(defaultValue = "false") Boolean isTemplate) {
        List<MaterialTaskPageVo> customerList = isTemplate != null && isTemplate ? new ArrayList<>() : ((PageOutput<MaterialTaskPageVo>) page(dto).getData()).getList();
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, MaterialTaskPageVo.class).automaticMergeHead(false).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(customerList);

        return RT.fileStream(bot.toByteArray(), "MaterialTask" + ExcelTypeEnum.XLSX.getValue());
    }

    @GetMapping(value = "/assign-page")
    @ApiOperation(value = "材料提交任务分员列表(分页)")
    @SaCheckPermission("materialtask:detail")
    public RT<PageOutput<MaterialTaskAssignVo>> assignPage(@Valid MaterialTaskAssignPageDto dto) {

        MPJLambdaWrapper<MaterialTaskAssign> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper
                .disableSubLogicDel()
                .eq(MaterialTaskAssign::getMaterialTaskId, dto.getMaterialTaskId())
                .select(MaterialTaskAssign::getId)
                .select(MaterialTaskAssign.class, x -> VoToColumnUtil.fieldsToColumns(MaterialTaskAssignVo.class).contains(x.getProperty()))
                .innerJoin(XjrUser.class, XjrUser::getId, MaterialTaskAssign::getUserId, ext -> ext.selectAs(XjrUser::getUserName, MaterialTaskAssignVo::getUserName))
                .leftJoin(UserDeptRelation.class, UserDeptRelation::getUserId, MaterialTypeAssign::getUserId)
                .leftJoin(Department.class, Department::getId, UserDeptRelation::getDeptId, ext -> ext.selectAs(Department::getName, MaterialTaskAssignVo::getDeptName))
        ;
        IPage<MaterialTaskAssignVo> page = materialTaskAssignService.selectJoinListPage(ConventPage.getPage(dto), MaterialTaskAssignVo.class, queryWrapper);
        PageOutput<MaterialTaskAssignVo> pageOutput = ConventPage.getPageOutput(page);
        return RT.ok(pageOutput);
    }

    @PostMapping(value = "/assign-add")
    @ApiOperation(value = "材料提交任务分员权限")
    @SaCheckPermission("materialtask:add")
    public RT<Boolean> assignAdd(@Valid @RequestBody AddMaterialTaskAssignDto dto){
        boolean isSuccess = materialTaskAssignService.add(dto);
        return RT.ok(isSuccess);
    }

    @DeleteMapping(value = "/assign-delete")
    @ApiOperation(value = "删除材料提交任务分员")
    @SaCheckPermission("materialtask:delete")
    public RT<Boolean> assignDelete(@Valid @RequestBody List<Long> ids){
        return RT.ok(materialTaskAssignService.delete(ids));
    }

    @PostMapping(value = "submited")
    @ApiOperation(value = "提交材料")
    @SaCheckPermission("materialtask:add")
    public RT<Boolean> submited(@Valid @RequestBody MaterialTaskAssignAppendixDto dto) {
        boolean isSuccess = materialTaskService.submited(dto);
        return RT.ok(isSuccess);
    }

    @PostMapping("/approved")
    @ApiOperation(value = "提交材料审核")
    public R approved(@Valid @RequestBody List<MaterialTaskAssignApprovedDto> dtos) {
        return R.ok(materialTaskAssignService.approved(dtos));
    }

    @PutMapping("/end")
    @ApiOperation(value = "提交材料结束 enabledMark 不用传")
    public R end(@Valid @RequestBody UpdateEnableMarkDto dto) {
        MaterialTask materialTask  = new MaterialTask();
        materialTask.setId(dto.getId());
        materialTask.setStatus(3);
        materialTaskService.updateById(materialTask);
        return R.ok(true);
    }

    @GetMapping(value = "/assign-list")
    @ApiOperation(value = "审核分员列表")
    @SaCheckPermission("materialtask:detail")
    public RT<List<MaterialTaskAssignListVo>> assignList(@Valid MaterialTaskAssignListDto dto) {
        return RT.ok(materialTaskService.assignList(dto));
    }

    @GetMapping("/view-contents")
    @ApiOperation(value = "查看填报的表单")
    public R viewContent(@Valid ViewContentDto dto) {
        return R.ok(formExecuteService.getInfoByTemplateId(new FormExecuteInfoDto(){{
            setTemplateId(dto.getTemplateId());
            setId(dto.getId());
        }}));
    }
}