package com.gci.boot.modules.vehicles.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gci.boot.annotation.Query.handle.QueryGenerator;
import com.gci.boot.annotation.permission.DataPermission;
import com.gci.boot.common.log.annotation.AddSysLog;
import com.gci.boot.common.util.StringUtil;
import com.gci.boot.common.validated.SaveValidated;
import com.gci.boot.common.validated.UpdateValidated;
import com.gci.boot.common.vo.Result;
import com.gci.boot.modules.msg.enums.SenderTypeEnum;
import com.gci.boot.modules.msg.enums.WorkOrderType;
import com.gci.boot.modules.msg.service.MsgPushService;
import com.gci.boot.modules.msg.vo.MsgRedisVO;
import com.gci.boot.modules.projects.entity.Projects;
import com.gci.boot.modules.projects.service.IProjectsService;
import com.gci.boot.modules.system.service.ISysUserService;
import com.gci.boot.modules.system.vo.LoginUser;
import com.gci.boot.modules.vehicles.entity.TbRepairInfo;
import com.gci.boot.modules.vehicles.entity.TbUpkeepBill;
import com.gci.boot.modules.vehicles.entity.TbUpkeepPlan;
import com.gci.boot.modules.vehicles.enums.UpkeepPlanStatusEnumEmployee;
import com.gci.boot.modules.vehicles.enums.UpkeepPlanStatusEnumLeader;
import com.gci.boot.modules.vehicles.mapper.TbUpkeepPlanMapper;
import com.gci.boot.modules.vehicles.service.ITbUpkeepPlanService;
import com.gci.boot.modules.vehicles.vo.CancelVO;
import com.gci.boot.modules.vehicles.vo.UpkeepInfoListVO;
import com.gci.boot.modules.vehicles.vo.UpkeepPlanObjectVO;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Api(tags="保养计划")
@Slf4j
@RestController
@RequestMapping("/vehicles/upkeepPlan")
public class UpKeepPlanController {

    @Autowired
    private ITbUpkeepPlanService upkeepPlanService;
    @Autowired
    private IProjectsService projectsService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private TbUpkeepPlanMapper upkeepPlanMapper;
    @Autowired
    private MsgPushService msgPushService;

    /**
     * 分页列表查询
     *
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AddSysLog("保养计划-分页列表查询")
    @GetMapping(value = "/list")
    @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbUpkeepPlanMapper.findUpkeepPlanList"})
    public Result<?> queryPageList(TbUpkeepPlan tbUpkeepPlan,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {

        Page<TbUpkeepPlan> page = new Page<TbUpkeepPlan>(pageNo, pageSize);
        IPage<TbUpkeepPlan> pageList = upkeepPlanService.getUpkeepPlanList(page, tbUpkeepPlan);
        return Result.ok(pageList);
    }

    /**
     * 添加
     */
    @AddSysLog("保养计划-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody @Validated(SaveValidated.class) TbUpkeepPlan tbUpkeepPlan) {
        Projects projects = projectsService.getById(tbUpkeepPlan.getProjectId());
        if(Objects.nonNull(projects)){
            tbUpkeepPlan.setProjectName(projects.getProjectName());
        }
        //手动生成
        tbUpkeepPlan.setSaveType(2);
        tbUpkeepPlan.setAuditStatus("1");
        tbUpkeepPlan.setPlanSaveTime(new Date());
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String username = "";
        if(Objects.nonNull(sysUser)){
            username = sysUser.getUsername();
        }
        if(Objects.nonNull(tbUpkeepPlan.getAttachmentList()) && tbUpkeepPlan.getAttachmentList().size()>0){
            tbUpkeepPlan.setAttachmentJson(JSONUtil.toJsonPrettyStr(tbUpkeepPlan.getAttachmentList()));
        }
        String format = DateUtil.format(new Date(),"yyyyMMddHHmmssSSS");
        tbUpkeepPlan.setOrderNo(format);

        tbUpkeepPlan.setCreateBy(username);
        upkeepPlanService.save(tbUpkeepPlan);
        //推送微信消息
        ThreadUtil.execAsync(()->{
            msgPushService.pushMsgToRedis(new MsgRedisVO(
                    SenderTypeEnum.YYWB.getSendType(),tbUpkeepPlan.getId(),
                    tbUpkeepPlan.getProjectId(), WorkOrderType.UPKEEP_PLAN.getType(),"未审批",
                    DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),projects.getProjectName() + "工单更新，请及时查看"));
        });
        return Result.ok("添加成功！");
    }

    /**
     * 编辑
     */
    @AddSysLog("保养计划-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody @Validated(UpdateValidated.class) TbUpkeepPlan tbUpkeepPlan) {
        Projects projects = projectsService.getById(tbUpkeepPlan.getProjectId());
        if(Objects.nonNull(projects)){
            tbUpkeepPlan.setProjectName(projects.getProjectName());
        }
        //审核未通过的编辑-》状态跳回未审核？
        TbUpkeepPlan one = upkeepPlanService.getById(tbUpkeepPlan.getId());

        if("3".equals(one.getAuditStatus())){
            tbUpkeepPlan.setAuditStatus("1");
        }
        if(Objects.nonNull(tbUpkeepPlan.getAttachmentList()) && tbUpkeepPlan.getAttachmentList().size()>0){
            tbUpkeepPlan.setAttachmentJson(JSONUtil.toJsonPrettyStr(tbUpkeepPlan.getAttachmentList()));
        }
        upkeepPlanService.updateById(tbUpkeepPlan);
        return Result.ok("编辑成功！");
    }

    /**
     * 删除
     */
    @AddSysLog("保养计划-删除")
    @DeleteMapping(value = "/realDelete")
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        upkeepPlanService.removeById(id);
        return Result.ok("删除成功！");
    }

    /**
     * 作废
     */
    @AddSysLog("保养计划-作废")
    @PostMapping(value = "/cancel")
    public Result<?> cancel(@RequestBody CancelVO vo) {
        String arg = StringUtil.checkString(vo.getCancelIdea(),200);
        if(StrUtil.isNotBlank(arg)){
            return Result.error(101,"作废原因 " + arg);
        }
        String realName = "";
        if(StrUtil.isNotBlank(vo.getRealname())){
            realName = vo.getRealname();
        }else{
            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            if(Objects.nonNull(sysUser)){
                realName = sysUser.getRealname();
            }
        }
        //批量作废
        List<String> ids = Arrays.asList(vo.getId().split(","));
        for(String oneId : ids){
            upkeepPlanService.update(new LambdaUpdateWrapper<TbUpkeepPlan>().eq(TbUpkeepPlan::getId,oneId)
                    .set(TbUpkeepPlan::getAuditStatus,"4")
                    .set(TbUpkeepPlan::getCancelIdea,vo.getCancelIdea())
                    .set(TbUpkeepPlan::getCancelPeople,realName)
                    .set(TbUpkeepPlan::getCancelTime,new Date()));
        }
        return Result.ok("作废成功！");
    }


    /**
     * 导出
     * @return
     */
    @AddSysLog("保养计划-导出")
    @GetMapping("/export")
    @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbUpkeepPlanMapper.findUpkeepAllList"})
    public Result<?> export(TbUpkeepPlan tbUpkeepPlan, HttpServletResponse response){
        try (OutputStream output = response.getOutputStream()){

            String fileName = "保养计划表.xlsx";
            try {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName);

            List<TbUpkeepPlan> list = upkeepPlanMapper.findUpkeepAllList(tbUpkeepPlan);
            EasyExcel.write(output, TbUpkeepPlan.class).sheet("保养计划").doWrite(list);

        } catch (IOException e) {
            return Result.error("导出错误！");
        }
        return Result.ok();
    }

    /**
     * 根据保养单id获取保养计划弹窗详情
     */
    @AddSysLog("保养计划-根据保养单id获取保养计划弹窗详情")
    @GetMapping(value = "/getUpkeepPlanObjectById")
    public Result<?> getUpkeepPlanObjectById(String id) {
        UpkeepPlanObjectVO vo = upkeepPlanService.getUpkeepPlanObjectById(id);
        return Result.ok(vo);
    }

    /**
     * 保养计划审核提交
     */
    @AddSysLog("保养计划-保养计划审核提交")
    @PostMapping(value = "/submitUpkeepPlan")
    public Result<?> submitUpkeepPlan(@RequestBody @Validated(SaveValidated.class) UpkeepPlanObjectVO vo) {

        if(redisTemplate.hasKey(vo.getId()+"_submitUpkeepPlan")){
            return Result.error(101,"该保养计划正在被操作中，无法操作，请刷新!");
        }else{
            redisTemplate.opsForValue().set(vo.getId()+"_submitUpkeepPlan", vo.getId(), 10, TimeUnit.SECONDS);
        }

        String result = "";
        try {
            result = upkeepPlanService.submitUpkeepPlan(vo);
        }catch (Exception e){
            e.printStackTrace();
            return Result.error(101,"提交失败：" + e.getMessage());
        }finally {
            redisTemplate.delete(vo.getId()+"_submitUpkeepPlan");
        }
        if(StrUtil.isNotBlank(result)){
            return Result.error(101,result);
        }
        return Result.ok("提交成功！");
    }

    /**
     * 规则生成保养计划
     */
    @AddSysLog("保养计划-规则生成保养计划")
    @GetMapping(value = "/ruleCreatePlan")
    public Result<?> ruleCreatePlan() {
        String str = upkeepPlanService.ruleCreatePlan();
        return Result.ok(str);
    }

    /**
     * 定时任务 规则生成保养计划 每天凌晨1点
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void scheduledRuleCreatePlan() {
        upkeepPlanService.ruleCreatePlan();
    }
}
