package com.ho.flow.controller;

import cn.hutool.core.lang.Snowflake;
import com.alibaba.druid.util.StringUtils;
import com.ho.common.tools.annotation.LogAnnotation;
import com.ho.common.tools.constant.ContextConstant;
import com.ho.common.tools.constant.RedisKeyConstant;
import com.ho.common.tools.entity.SimpleUser;
import com.ho.common.tools.entity.UserDetailRespVO;
import com.ho.common.tools.exception.BaseResponseCode;
import com.ho.common.tools.exception.BusinessException;
import com.ho.common.tools.exception.DataResult;
import com.ho.common.tools.service.RedisService;
import com.ho.common.tools.util.PageResult;
import com.ho.flow.common.FlowTool;
import com.ho.flow.constant.WorkOrderConstant;
import com.ho.flow.service.FlowWorkOrderService;
import com.ho.flow.service.WorkOrderCirculationService;
import com.ho.flow.service.WorkOrderHisService;
import com.ho.flow.vo.WorkOrderOld;
import com.ho.flow.vo.WorkOrderCirculation;
import com.ho.flow.vo.req.workorder.*;
import com.ho.flow.vo.resp.workorder.WorkOrderCirculationRespVO;
import com.ho.flow.vo.resp.workorder.WorkOrderOldPageRespVO;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.*;

/**
 * @author fancl
 * @desc: 工作流 工单
 * @date 2023/1/22
 */
@RestController
@RequestMapping(ContextConstant.FLOW_CONTEXT +"workOrderHis")
@Slf4j
public class WorkOrderHisController {

    @Autowired
    WorkOrderHisService workOrderHisService;

    @Autowired
    WorkOrderCirculationService workOrderCirculationService;

    @Autowired
    FlowWorkOrderService flowWorkOrderService;

    @Autowired
    RedisService redisService;

    @Autowired
    Snowflake snowflake;

    @Autowired
    FlowTool flowTool;

    //执行工单的岗位
    @Value("#{'${flow.workOrder.doing}'.split(',')}")
    String[] doing;

    //验收工单的岗位
    @Value("#{'${flow.workOrder.check}'.split(',')}")
    String[] check;

    //评价工单的岗位
    @Value("#{'${flow.workOrder.appraise}'.split(',')}")
    String[] appraise;


    //工单结合工作流进行审批控制, 能够分配和执行任务的是具有特定岗位的人员
    @PostMapping("add")
    @ApiOperation(value = "新增工单")
    //@LogAnnotation(title = "工单管理", action = "新增工单信息")
    public DataResult add(@RequestBody  @Valid WorkOrderAddReq vo ,HttpServletRequest request) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser simpleUser = redisService.getSimpleUserByToken(token);
        String workOrderId = flowTool.getNextWorkOrderId(WorkOrderConstant.IdTypeWorkOrder);
        //原有工单流程中增加工作流
        workOrderHisService.insertStation(vo,simpleUser,workOrderId);

        return DataResult.success();
    }



    @GetMapping("detail/{orderId}")
    @ApiOperation(value = "根据工单id查询工单详情")
    public DataResult<WorkOrderOld> selectById(@PathVariable @Valid String orderId) {
        WorkOrderOld workOrderOld = workOrderHisService.selectById(orderId);
        return DataResult.success(workOrderOld);
    }

    @PostMapping("update")
    @ApiOperation(value = "修改工单")
    @LogAnnotation(title = "工单管理", action = "修改工单信息")
    public DataResult update(@RequestBody @Valid WorkOrderUpdateReq vo , HttpServletRequest request) {
        //判断工单
        WorkOrderOld workOrderOld = workOrderHisService.findByOrderId(vo.getOrderId());
        if (workOrderOld == null) {
            //没找到数据
            throw new BusinessException(BaseResponseCode.DATA_NOT_EXISTS);
        }
        //工单状态必须是待分配  人工派单
        if(!WorkOrderConstant.WorkOrderStatus.toBeAllocate.equals(workOrderOld.getWorkOrderStatus())) {
            throw new BusinessException(BaseResponseCode.WORK_ORDER_STATUS_MUST_BE_NOT_EDIT);
        }
        if(!WorkOrderConstant.WorkOrderType.dispatcher.equals(workOrderOld.getWorkOrderType())){
            throw new BusinessException(BaseResponseCode.WORK_ORDER_TYPE_NOT_MANUAL_CANNOT_BE_MODIFIED);
        }

        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser simpleUser = redisService.getSimpleUserByToken(token);
        workOrderHisService.updateWorkOrder(vo,simpleUser);
        return DataResult.success();
    }

    //一次只删除一个
    @PostMapping("delete")
    @ApiOperation(value = "删除工单")
    @LogAnnotation(title = "工单管理", action = "删除工单信息")
    public DataResult delete(@RequestBody @Valid WorkDeleteOrderReq req) {
        //判断工单
        WorkOrderOld workOrderOld = workOrderHisService.findByOrderId(req.getOrderId());
        if(workOrderOld == null) {
            //没找到数据
            throw new BusinessException(BaseResponseCode.DATA_NOT_EXISTS);
        }
        if(!WorkOrderConstant.WorkOrderStatus.toBeAllocate.equals(workOrderOld.getWorkOrderStatus())) {
            throw new BusinessException(BaseResponseCode.EXISTENCE_NOT_PENDING_ASSIGNMENT_CANNOT_DELETED);
        }
        workOrderHisService.delete(req.getOrderId());
        return DataResult.success();
    }

    //  ctrl+shift+/
   /* @PostMapping("delete")
    @ApiOperation(value = "删除工单")
    @LogAnnotation(title = "工单管理", action = "删除工单信息")
    public DataResult delete(@RequestBody List<String> orderIds) {
        //判断工单
        for (String orderId : orderIds) {
            WorkOrder workOrder = workOrderService.findByOrderId(orderId);
             if(workOrder == null) {
                //没找到数据
                throw new BusinessException(BaseResponseCode.DATA_NOT_EXISTS);
            }
            if(!WorkOrderConstant.WorkOrderStatus.toBeAllocate.equals(workOrder.getWorkOrderStatus())) {
                throw new BusinessException(BaseResponseCode.EXISTENCE_NOT_PENDING_ASSIGNMENT_CANNOT_DELETED);
            }
        }
        workOrderService.deleteWorkOrder(orderIds);
        return DataResult.success();
    }*/

    //代办数据来自工作流
    @PostMapping("needToDoList")
    @ApiOperation(value = "待办的工单列表")
    public DataResult<PageResult<WorkOrderOldPageRespVO>> needToDoList(@RequestBody @Valid WorkOrderPageReq vo, HttpServletRequest request) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        UserDetailRespVO userDetailRespVO = redisService.getUserDetailByToken(token);
        //岗位列表
        List<String> positions = userDetailRespVO.getPositions();
        List<WorkOrderOldPageRespVO> list = new ArrayList<>();
        //没有岗位啥也做不了
        if(positions==null ||positions.isEmpty()){
            log.error("positions is Empty !!");
            return DataResult.success(list);
        }
        //查询SimpleUser
        SimpleUser simpleUser = redisService.getSimpleUserByToken(token);
        UserDetailRespVO userDetail = redisService.getUserDetailByToken(token);
        List<Integer> stationIds = simpleUser.getStationIds();
        if(stationIds==null || stationIds.isEmpty()){
            log.error("stationIds is Empty !!");
            return DataResult.success(list);
        }
        List<String> stationIdsList = flowWorkOrderService.intToString(stationIds);
        //是否有分配权
        boolean bDoingUser = false;
        //是否有验收工单权限
        boolean bCheckUser = false;
        //是否有评价权限
        boolean bAppraiseUser = false;
        //租户id
        String tenantId = simpleUser.getGroupId().toString();
        //定义三种集合,待分配 ,待执行 ,待验收
        Map<String,String> toDistributeMap = new HashMap<>();
        Map<String,String> toDoMap = new HashMap<>();
        Map<String,String> toCheckMap = new HashMap<>();
        //执行
        if(flowWorkOrderService.matchPermit(positions ,doing)){
            bDoingUser = true;
            List<String> candidateUsers =new ArrayList<>();
            candidateUsers.add(WorkOrderConstant.canDistributeOrder);
            //查询可分配的代办
            toDistributeMap = flowWorkOrderService.queryToBeDoneMap(WorkOrderConstant.categoryWorkOrder, WorkOrderConstant.canDistributeOrder,candidateUsers,
                    stationIdsList, tenantId);
        }
        //验收
        if(flowWorkOrderService.matchPermit(positions ,check)){
            bCheckUser = true;
            toDoMap = flowWorkOrderService.queryPersonalTask(WorkOrderConstant.categoryWorkOrder, userDetail.getUsername(), tenantId);
        }
        //是否可以验收工单
        if(flowWorkOrderService.matchPermit(positions ,appraise)){
            bAppraiseUser = true;
            //候选角色
            List<String> candidateUsers =new ArrayList<>();
            candidateUsers.add(WorkOrderConstant.canCheckOrder);
            toCheckMap = flowWorkOrderService.queryToBeDoneMap(WorkOrderConstant.categoryWorkOrder, WorkOrderConstant.canCheckOrder,candidateUsers,
                    stationIdsList, tenantId);
        }
        //如果 stationId没传 要查所辖电站的数据
        if(org.springframework.util.StringUtils.isEmpty(vo.getStationId())){
            vo.setStationIds(stationIds);
        }
        //因为是使用 stationIds 查询的,不为空时那么把stationId加进去
        //查询电站时只用  stationIds 就行了
        else{
            stationIds = new ArrayList<>();
            stationIds.add(vo.getStationId());
            vo.setStationIds(stationIds);
        }
        //从得到的几个代办map中处理得到工单id列表
        List<String> orderIdList = flowWorkOrderService.getOrderIdList(toDistributeMap, toDoMap, toCheckMap);
        vo.setGroupId(simpleUser.getGroupId());
        vo.setOrderIds(orderIdList);
        //根据代办查工单,再根据工单状态确定下一步动作
        //1.待分配的工单 2.待操作的工单(接受) 3.待验收的
        PageResult<WorkOrderOldPageRespVO> result = workOrderHisService.selectPage(vo,simpleUser);
        return DataResult.success(result);
    }


    @PostMapping("allocate")
    @ApiOperation(value = "分配工单")
    @LogAnnotation(title = "工单管理", action = "分配工单")
    public DataResult allocate(@RequestBody @Valid WorkOrderApplyReqVO reqVO, HttpServletRequest request) {
        //判断必填参数
        if(StringUtils.isEmpty(reqVO.getOrderId())){
            throw new BusinessException(BaseResponseCode.WORK_ORDER_ID_REQUIRED);
        }
        if(StringUtils.isEmpty(reqVO.getToId())){
            throw new BusinessException(BaseResponseCode.WORK_ORDER_TO_ID_REQUIRED);
        }
        if(StringUtils.isEmpty(reqVO.getPhone())){
            throw new BusinessException(BaseResponseCode.WORK_ORDER_PHONE_REQUIRED);
        }
        //当前登陆人
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        UserDetailRespVO userDetail = redisService.getUserDetailByToken(token);
        //使用岗位判断是否可以分配工单
        List<String> positions = userDetail.getPositions();
        if(positions.isEmpty()){
            throw new BusinessException(BaseResponseCode.IS_NOT_ROLE_WORK_ORDER_LEADER);
        }
        //岗位不为空,判断是否包含岗位权限,只要包含一个就是有权限
        //没有对应岗位,报个提示
        if(!flowWorkOrderService.matchPermit(positions, doing)){
            throw new BusinessException(BaseResponseCode.IS_NOT_ROLE_WORK_ORDER_LEADER);
        }
        SimpleUser simpleUser = redisService.getSimpleUserByToken(token);

        workOrderHisService.allocateOrder(reqVO, simpleUser);
        return DataResult.success();
    }

    //    接受工单acceptWorkOrder
    @PostMapping("acceptWorkOrder")
    @ApiOperation(value = "接受工单")
    @LogAnnotation(title = "工单管理", action = "接受工单")
    public DataResult acceptWorkOrder(@RequestBody @Valid WorkOrderApplyReqVO vo,HttpServletRequest request) {
        //判断工单
        WorkOrderOld workOrderOld = workOrderHisService.findByOrderId(vo.getOrderId());
        if (workOrderOld == null) {
            //没找到数据
            throw new BusinessException(BaseResponseCode.DATA_NOT_EXISTS);
        }
        //工单状态必须是已分配
        if (!WorkOrderConstant.WorkOrderStatus.allocated.equals(workOrderOld.getWorkOrderStatus())) {
            throw new BusinessException(BaseResponseCode.WORK_ORDER_STATUS_NOT_ASSIGNED_CANNOT_CONFIRMED);
        }
        //接受后将状态改为处理中
        workOrderOld.setWorkOrderStatus(WorkOrderConstant.WorkOrderStatus.working);
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser simpleUser = redisService.getSimpleUserByToken(token);
        //生成流转记录
        // workOrderAction  指定当前动作
        WorkOrderCirculation workOrderAccept = new WorkOrderCirculation();
        workOrderAccept.setId(snowflake.nextId());
        workOrderAccept.setOrderId(vo.getOrderId());
        workOrderAccept.setFromId(simpleUser.getUserId());
        workOrderAccept.setToId(vo.getToId());
        workOrderAccept.setCreateTime(new Date());
        workOrderAccept.setWorkOrderAction(WorkOrderConstant.WorkOrderAction.workOrderDo);
        workOrderHisService.acceptWorkOrder(workOrderOld,workOrderAccept);
        return DataResult.success();
    }

    //    退回工单returnWorkOrder
    @PostMapping("returnWorkOrder")
    @ApiOperation(value = "退回工单")
    @LogAnnotation(title = "工单管理", action = "退回工单")
    public DataResult returnWorkOrder(@RequestBody @Valid WorkOrderApplyReqVO vo,HttpServletRequest request) {
        //判断工单
        WorkOrderOld workOrderOld = workOrderHisService.findByOrderId(vo.getOrderId());
        if (workOrderOld == null) {
            //没找到数据
            throw new BusinessException(BaseResponseCode.DATA_NOT_EXISTS);
        }
        //工单状态必须是已分配的状态  (2,3都可以退回)
        if (!WorkOrderConstant.WorkOrderStatus.allocated.equals(workOrderOld.getWorkOrderStatus()) && !WorkOrderConstant.WorkOrderStatus.working.equals(workOrderOld.getWorkOrderStatus()) ) {
            throw new BusinessException(BaseResponseCode.WORK_ORDER_STATUS_NOT_ASSIGNED_CANNOT_RETURNED);
        }
        //退回将状态改为待分配状态
        workOrderOld.setWorkOrderStatus(WorkOrderConstant.WorkOrderStatus.toBeAllocate);
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser simpleUser = redisService.getSimpleUserByToken(token);
        //生成流转记录
        // workOrderAction  指定当前动作
        WorkOrderCirculation workOrderReturn = new WorkOrderCirculation();
        workOrderReturn.setId(snowflake.nextId());
        workOrderReturn.setOrderId(workOrderOld.getOrderId());
        workOrderReturn.setFromId(simpleUser.getUserId());
        workOrderReturn.setToId(vo.getToId());
        workOrderReturn.setCreateTime(new Date());
        workOrderReturn.setWorkOrderAction(WorkOrderConstant.WorkOrderAction.workOrderReject);
        workOrderReturn.setDesc(vo.getDistributionDesc());
        workOrderHisService.returnWorkOrder(workOrderOld,workOrderReturn);
        return DataResult.success();
    }

    //    关闭工单closeJob
    @PostMapping("closeWorkOrder")
    @ApiOperation(value = "关闭工单")
    @LogAnnotation(title = "工单管理", action = "关闭工单")
    public DataResult closeWorkOrder(@RequestBody @Valid WorkOrderApplyReqVO vo,HttpServletRequest request) {
        //判断工单
        WorkOrderOld workOrderOld = workOrderHisService.findByOrderId(vo.getOrderId());
        if (workOrderOld == null) {
            //没找到数据
            throw new BusinessException(BaseResponseCode.DATA_NOT_EXISTS);
        }
        //工单状态必须是处理中的状态
        if (!WorkOrderConstant.WorkOrderStatus.working.equals(workOrderOld.getWorkOrderStatus())) {
            throw new BusinessException(BaseResponseCode.WORK_ORDER_STATUS_NOT_PROCESS_CANNOT_CLOSED);
        }
        //关闭工单时将状态改为已完成的状态
        workOrderOld.setWorkOrderStatus(WorkOrderConstant.WorkOrderStatus.finished);
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser simpleUser = redisService.getSimpleUserByToken(token);
        //生成流转记录
        // workOrderAction  指定当前动作
        WorkOrderCirculation workOrderClose = new WorkOrderCirculation();
        workOrderClose.setId(snowflake.nextId());
        workOrderClose.setOrderId(workOrderOld.getOrderId());
        workOrderClose.setFromId(simpleUser.getUserId());
        workOrderClose.setToId(vo.getToId());
        workOrderClose.setCreateTime(new Date());
        workOrderClose.setDesc(vo.getDistributionDesc());
        //原来对应工单关闭,现在对应验收完成
        //workOrderClose.setWorkOrderAction(WorkOrderConstant.WorkOrderAction.workOrderClose);
        workOrderClose.setWorkOrderAction(WorkOrderConstant.WorkOrderAction.workOrderCheckComplete);
        workOrderHisService.closeWorkOrder(workOrderOld,workOrderClose);
        return DataResult.success();
    }

    //一个人可以查询的工单是自己所辖电站的全部工单
    @PostMapping("page")
    @ApiOperation(value = "查询工单")
    public DataResult<PageResult<WorkOrderOldPageRespVO>> selectByPage(@RequestBody @Valid WorkOrderPageReq vo, HttpServletRequest request) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        UserDetailRespVO userDetailRespVO = redisService.getUserDetailByToken(token);
        List<String> roles = userDetailRespVO.getRoles();
        //查询SimpleUser
        SimpleUser simpleUser = redisService.getSimpleUserByToken(token);
        List<Integer> stationIds = simpleUser.getStationIds();
        //如果 stationId没传 要查所辖电站的数据
        if(org.springframework.util.StringUtils.isEmpty(vo.getStationId())){
            vo.setStationIds(stationIds);
        }
        //因为是使用stationIds查询的,不为空时那么把stationId加进去
        else{
            stationIds = new ArrayList<>();
            stationIds.add(vo.getStationId());
            vo.setStationIds(stationIds);
        }
        String roleLeader = null;
        String roleWorker = null;
        //工单使用岗位进行流程控制,不再使用角色
        //
        /*for (String role : roles) {
            if (CommonConstant.ROLE_WORK_ORDER_LEADER.equals(role)){
                roleLeader = CommonConstant.ROLE_WORK_ORDER_LEADER;
            }else if (CommonConstant.ROLE_WORK_ORDER_DO.equals(role)){
                roleWorker = CommonConstant.ROLE_WORK_ORDER_DO;
            }
        }*/

        //判断3种情况(1都没有; 2:worker 3: leader  或 leader he worker 或   leader	)
        //情况1
        /*if(roleLeader ==null &&roleWorker ==null){
            vo.setRoleOther(CommonConstant.ROLE_WORK_ORDER_OTHER);
            vo.setFromId(userDetailRespVO.getUserId());
            vo.setToId(userDetailRespVO.getUserId());
        }else if(roleLeader ==null && roleWorker !=null){
            //
            vo.setRoleWorker(CommonConstant.ROLE_WORK_ORDER_DO);
            vo.setFromId(userDetailRespVO.getUserId());
            vo.setToId(userDetailRespVO.getUserId());
        }else{
            vo.setRoleLeader(CommonConstant.ROLE_WORK_ORDER_LEADER);
            vo.setToId(userDetailRespVO.getUserId());
            vo.setFromId(userDetailRespVO.getUserId());
        }*/
        //能查到的工单和这个人的角色或岗位没有关系,只和该用户所辖电站有关

        PageResult<WorkOrderOldPageRespVO> result = workOrderHisService.selectPage(vo,simpleUser);
        return DataResult.success(result);
    }

    @PostMapping("hisPage")
    @ApiOperation(value = "查询历史工单")
    public DataResult<PageResult<WorkOrderOldPageRespVO>> selectHisByPage(@RequestBody @Valid WorkOrderPageReq vo, HttpServletRequest request) {
        String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
        SimpleUser simpleUser = redisService.getSimpleUserByToken(token);
        //如果 stationId没传 要查所辖电站的数据
        if(org.springframework.util.StringUtils.isEmpty(vo.getStationId())){
            vo.setStationIds(simpleUser.getStationIds());
        }
        PageResult<WorkOrderOldPageRespVO> result = workOrderHisService.selectHisPage(vo);
        return DataResult.success(result);
    }

    @GetMapping("circulation/{orderId}")
    @ApiOperation(value = "查询工单流转记录")
    public DataResult<List<WorkOrderCirculationRespVO>> getWorkOrderControllerList(@PathVariable @Valid String orderId) {
        List<WorkOrderCirculationRespVO> list = workOrderCirculationService.selectByOrderId(orderId);
        return DataResult.success(list);
    }
}
