package com.cpop.oam.business.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.cpop.api.tencent.wxWork.handler.WebHookSendHandler;
import com.cpop.common.utils.StringUtils;
import com.cpop.common.utils.bean.BeanUtils;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.base.entity.loginInfo.OamStaffLoginInfo;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.service.RedisService;
import com.cpop.core.utils.SecurityUtils;
import com.cpop.core.utils.SpringUtils;
import com.cpop.oam.business.bo.TaskStaffGroupBo;
import com.cpop.oam.business.entity.Task;
import com.cpop.oam.business.entity.TaskStaffGroup;
import com.cpop.oam.business.mapper.TaskStaffGroupMapper;
import com.cpop.oam.business.service.StaffService;
import com.cpop.oam.business.service.TaskService;
import com.cpop.oam.business.service.TaskStaffGroupService;
import com.cpop.oam.business.vo.StaffInfoVo;
import com.cpop.oam.business.vo.TaskStaffGroupVo;
import com.cpop.oam.framework.constant.WebHookKeyConstant;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static com.cpop.oam.business.entity.table.StaffTableDef.STAFF;
import static com.cpop.oam.business.entity.table.TaskStaffGroupTableDef.TASK_STAFF_GROUP;

/**
 * OAM-任务-关联员工任务组表 服务层实现。
 *
 * @author DB
 * @since 2023-09-18
 */
@Service("taskStaffGroupService")
public class TaskStaffGroupServiceImpl extends ServiceImpl<TaskStaffGroupMapper, TaskStaffGroup>
        implements TaskStaffGroupService {

    /**
     * 技术模块-今日事务-任务成员组列
     *
     * @param taskId 任务id
     * @return List<TaskStaffGroupVo>
     * @author DB
     * @since 2023/12/04
     */
    @Override
    public List<TaskStaffGroupVo> getTaskStaffGroupList(String taskId) {
        return this.listAs(QueryWrapper.create()
                .select(TASK_STAFF_GROUP.ALL_COLUMNS)
                .select(STAFF.NAME.as(TaskStaffGroupVo::getStaffName))
                .from(TASK_STAFF_GROUP)
                .leftJoin(STAFF)
                .on(STAFF.ID.eq(TASK_STAFF_GROUP.STAFF_ID))
                .where(TASK_STAFF_GROUP.TASK_ID.eq(taskId)), TaskStaffGroupVo.class);
    }

    /**
     * 技术模块-今日事务-新增任务小组成员
     *
     * @param bo 请求参数
     * @author DB
     * @since 2023/12/04
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertTaskStaffGroup(TaskStaffGroupBo bo) {
        // 获取任务
        TaskService taskService = SpringUtils.getBean(TaskService.class);
        Task task = taskService.getById(bo.getTaskId());
        //  当前操作员工是否是主要负责人，不是抛出异常
        JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo();
        if (!StringUtils.equals(task.getResponsibleStaffId(), loginUserInfo.getString("id"))) {
            throw new ServiceException("当前操作员工不是当前任务主要负责人，不允许操作当前任务！");
        }
        // 查询当前添加的员工是否存在在此任务中
        long count = this.count(QueryWrapper.create()
                .where(TASK_STAFF_GROUP.TASK_ID.eq(bo.getTaskId()))
                .and(TASK_STAFF_GROUP.STAFF_ID.eq(bo.getStaffId())));
        if (count > 0) {
            throw new ServiceException("当前员工已存在任务中，请添加其他员工或调整此员工绩点");
        }
        // 获取此任务下关联的主要负责人信息
        TaskStaffGroup responsibleStaff = this.getOne(QueryWrapper.create()
                .where(TASK_STAFF_GROUP.TASK_ID.eq(bo.getTaskId()))
                .and(TASK_STAFF_GROUP.STAFF_ID.eq(task.getResponsibleStaffId())));
        int balance = responsibleStaff.getGradePoint() - bo.getGradePoint();
        if (balance < 0) {
            throw new ServiceException("主要负责人绩点不足，请重新调整!");
        } else {
            responsibleStaff.setGradePoint(responsibleStaff.getGradePoint() - bo.getGradePoint());
        }
        // 存入数据
        TaskStaffGroup taskStaffGroup = BeanUtils.mapToClass(bo, TaskStaffGroup.class);
        this.save(taskStaffGroup);
        this.updateById(responsibleStaff);
        // 企微通知绩点调整人员
        List<String> phoneList = new ArrayList<String>();
        phoneList.add(loginUserInfo.getString("phoneNumber"));
        // 获取新增员工信息
        StaffInfoVo staffInfo = SpringUtils.getBean(StaffService.class).getStaffInfo(bo.getStaffId());
        phoneList.add(staffInfo.getPhoneNumber());
        try {
            SpringUtils.getBean(WebHookSendHandler.class).webHookSendText(WebHookKeyConstant.PRODUCT_BOT, phoneList,
                    "任务:" + task.getTaskContent() + "\n" +
                            loginUserInfo.getString("name") + "您的绩点调整为" + responsibleStaff.getGradePoint() + "\n" + staffInfo.getName()
                            + "您新加入任务:" + task.getTaskContent() + "绩点为:" + bo.getGradePoint(),
                    false);
        } catch (IOException e) {
            throw new ServiceException("发送通知失败!");
        }
    }

    /**
     * 技术模块-今日事务-修改员工任务绩点
     *
     * @param bo 请求参数
     * @author DB
     * @since 2023/12/04
     */
    @Override
    public void updateStaffGradePoint(TaskStaffGroupBo bo) {
        // 获取任务主负责人相关绩点
        TaskService taskService = SpringUtils.getBean(TaskService.class);
        Task task = taskService.getById(bo.getTaskId());
        if (null == task) {
            throw new ServiceException("获取任务失败！请联系相关人员!");
        }
        JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo();
        if (!StringUtils.equals(task.getResponsibleStaffId(), loginUserInfo.getString("id"))) {
            throw new ServiceException("当前操作员工不是当前任务主要负责人，不允许操作当前任务！");
        }
        if (StringUtils.equals(bo.getStaffId(), task.getResponsibleStaffId())) {
            throw new ServiceException("不允许直接修改主要负责人绩点");
        }
        // 获取此任务下关联的主要负责人信息
        TaskStaffGroup responsibleStaffTaskInfo = this.getOne(QueryWrapper.create()
                .where(TASK_STAFF_GROUP.TASK_ID.eq(bo.getTaskId()))
                .and(TASK_STAFF_GROUP.STAFF_ID.eq(task.getResponsibleStaffId())));
        // 自身原绩点
        TaskStaffGroup oldStaffTaskInfo = this.getById(bo.getId());
        // 增加
        if (bo.getGradePoint() > oldStaffTaskInfo.getGradePoint()) {
            // 判断主负责人绩点够不够减
            if (responsibleStaffTaskInfo.getGradePoint() < (bo.getGradePoint() - oldStaffTaskInfo.getGradePoint())) {
                throw new ServiceException("当前主负责人绩点不够，请重新调整！");
            }
            // 添加的绩点
            int addGradePoint = bo.getGradePoint() - oldStaffTaskInfo.getGradePoint();
            responsibleStaffTaskInfo.setGradePoint(responsibleStaffTaskInfo.getGradePoint() - addGradePoint);
            // 更新主负责人绩点
            this.updateById(responsibleStaffTaskInfo);
        } else {
            // 减少的绩点
            int reduceGradePoint = oldStaffTaskInfo.getGradePoint() - bo.getGradePoint();
            responsibleStaffTaskInfo.setGradePoint(responsibleStaffTaskInfo.getGradePoint() + reduceGradePoint);
            // 更新主负责人绩点
            this.updateById(responsibleStaffTaskInfo);
        }
        // 更新绩点
        this.updateChain()
                .set(TASK_STAFF_GROUP.GRADE_POINT, bo.getGradePoint())
                .where(TASK_STAFF_GROUP.TASK_ID.eq(bo.getTaskId()))
                .and(TASK_STAFF_GROUP.STAFF_ID.eq(bo.getStaffId()))
                .update();
        // 企微通知绩点调整人员
        List<String> phoneList = new ArrayList<String>();
        phoneList.add(loginUserInfo.getString("phoneNumber"));
        // 获取新增员工信息
        StaffInfoVo staffInfo = SpringUtils.getBean(StaffService.class).getStaffInfo(bo.getStaffId());
        phoneList.add(staffInfo.getPhoneNumber());
        try {
            SpringUtils.getBean(WebHookSendHandler.class).webHookSendText(WebHookKeyConstant.PRODUCT_BOT, phoneList,
                    "任务:" + task.getTaskContent() + "\n" +
                            loginUserInfo.getString("name") + "您的绩点调整为" + responsibleStaffTaskInfo.getGradePoint() + "\n"
                            + staffInfo.getName() + "您的绩点调整为:" + bo.getGradePoint(),
                    false);
        } catch (IOException e) {
            throw new ServiceException("发送通知失败!");
        }
    }

    /**
     * 技术模块-今日事务-删除成员组
     *
     * @param id 任务组id
     * @author DB
     * @since 2023/12/04
     */
    @Override
    public void removeTaskStaffGroupById(String id) {
        // 获取任务
        TaskStaffGroup taskStaffGroup = this.getById(id);
        TaskService taskService = SpringUtils.getBean(TaskService.class);
        Task task = taskService.getById(taskStaffGroup.getTaskId());
        JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo();
        if (!StringUtils.equals(task.getResponsibleStaffId(), loginUserInfo.getString("id"))) {
            throw new ServiceException("当前操作员工不是当前任务主要负责人，不允许操作当前任务！");
        }
        // 不允许删除主要负责人
        if (StringUtils.equals(taskStaffGroup.getStaffId(), task.getResponsibleStaffId())) {
            throw new ServiceException("任务主要负责人不允许删除!");
        }
        // 添加绩点给主要负责人
        TaskStaffGroup responsibleStaffInfo = this.getOne(QueryWrapper.create()
                .where(TASK_STAFF_GROUP.TASK_ID.eq(taskStaffGroup.getTaskId()))
                .and(TASK_STAFF_GROUP.STAFF_ID.eq(task.getResponsibleStaffId())));
        responsibleStaffInfo.setGradePoint(responsibleStaffInfo.getGradePoint() + taskStaffGroup.getGradePoint());
        this.updateById(responsibleStaffInfo);
        this.removeById(id);
    }
}
