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

import cn.binarywang.wx.miniapp.api.WxMaQrcodeService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import com.alibaba.fastjson.JSONObject;
import com.cpop.api.tencent.wxWork.handler.WebHookSendHandler;
import com.cpop.common.constant.Constants;
import com.cpop.common.utils.StringUtils;
import com.cpop.common.utils.bean.BeanUtils;
import com.cpop.core.base.entity.PageDomain;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.base.table.SysConfig;
import com.cpop.core.service.CoreService;
import com.cpop.core.service.RedisService;
import com.cpop.core.utils.SecurityUtils;
import com.cpop.core.utils.SpringUtils;
import com.cpop.core.utils.sql.SqlUtils;
import com.cpop.oam.business.bo.TaskDemandBo;
import com.cpop.oam.business.bo.TaskDemandPageBo;
import com.cpop.oam.business.bo.TaskDemandUrgentBo;
import com.cpop.oam.business.entity.Task;
import com.cpop.oam.business.entity.TaskDemand;
import com.cpop.oam.business.mapper.TaskDemandMapper;
import com.cpop.oam.business.service.CommonService;
import com.cpop.oam.business.service.TaskDemandService;
import com.cpop.oam.business.service.TaskService;
import com.cpop.oam.business.vo.TaskDemandPageVo;
import com.cpop.oam.business.vo.TaskDemandUrgentVo;
import com.cpop.oam.framework.constant.WebHookKeyConstant;
import com.cpop.oam.framework.enums.OamConfigEnum;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

import static com.cpop.core.base.table.table.SysUserTableDef.SYS_USER;
import static com.cpop.oam.business.entity.table.StaffTableDef.STAFF;
import static com.cpop.oam.business.entity.table.TaskDemandTableDef.TASK_DEMAND;
import static com.cpop.oam.business.entity.table.TaskTableDef.TASK;
import static com.cpop.system.business.entity.table.BrandTableDef.BRAND;
import static com.cpop.system.business.entity.table.StoreTableDef.STORE;

/**
 * OAM-任务-需求表 服务层实现。
 *
 * @author DB
 * @since 2023-09-18
 */
@Service("taskDemandService")
public class TaskDemandServiceImpl extends ServiceImpl<TaskDemandMapper, TaskDemand> implements TaskDemandService {

    /**
     * 工单模块-需求-需求分页列表
     * @author DB
     * @param bo 查询参数
     * @since 2023-11-30 17:26:24
     */
    @Override
    public Page<TaskDemandPageVo> getTaskDemandPage(TaskDemandPageBo bo) {
        // 分页主体应该是任务
        QueryWrapper queryWrapper = QueryWrapper.create();
        if (null != bo.getTaskStatus()) {
            switch (bo.getTaskStatus()) {
                case 10:
                    queryWrapper.and(TASK.TASK_STATUS.eq(10));
                    break;
                // 待评估
                case 0:
                    queryWrapper.and(TASK.TASK_STATUS.eq(0));
                    break;
                // 待领取
                case 1:
                    queryWrapper.and(TASK.TASK_STATUS.in(1));
                    break;
                // 处理中
                case 2:
                    queryWrapper.and(TASK.TASK_STATUS.in(2, 4));
                    break;
                // 已完成
                default:
                    queryWrapper.and(TASK.TASK_STATUS.in(8, 9));
            }
        } else {
            queryWrapper.and(TASK.TASK_STATUS.eq(0));
        }
        // 重新定义列表
        PageDomain pageDomain = SqlUtils.getInstance().getPageDomain();
        return this.mapper.paginateAs(Page.of(pageDomain.getPageNum(), pageDomain.getPageSize()),
                queryWrapper
                        .select(TASK_DEMAND.ID,
                                TASK_DEMAND.BRAND_ID,
                                TASK_DEMAND.STORE_ID,
                                TASK_DEMAND.CREATE_TIME,
                                TASK_DEMAND.UPDATE_USER_ID,
                                TASK_DEMAND.UPDATE_TIME)
                        // 品牌
                        .select(BRAND.BRAND_NAME)
                        // 校区
                        .select(STORE.STORE_NAME)
                        // 任务
                        .select(TASK.TASK_CONTENT,
                                TASK.RECORD_STAFF_ID,
                                TASK.IS_URGENT,
                                TASK.ATTACHMENT_URL,
                                TASK.EXPECTED_COMPLETION_DATE,
                                TASK.TASK_RATING,
                                TASK.RESPONSIBLE_STAFF_ID,
                                TASK.TASK_RECEIPT_TIME,
                                TASK.REMARK,
                                TASK.COMPLETION_DATE,
                                TASK.TEST_TO_FINISH_URL)
                        .from(TASK_DEMAND)
                        // 任务需求表
                        .leftJoin(TASK)
                        .on(TASK.ID.eq(TASK_DEMAND.TASK_ID))
                        // 校区表
                        .leftJoin(STORE)
                        .on(STORE.ID.eq(TASK_DEMAND.STORE_ID))
                        // 品牌表
                        .leftJoin(BRAND)
                        .on(BRAND.ID.eq(TASK_DEMAND.BRAND_ID))
                        .where(TASK.TASK_TYPE.eq(1))
                        .and(TASK.TASK_CONTENT.like(bo.getTaskContent()))
                        .and(STORE.STORE_NAME.like(bo.getBrandOrStore()).or(BRAND.BRAND_NAME.like(bo.getBrandOrStore()))),
                TaskDemandPageVo.class,
                // 记录员工名
                item -> item.field(TaskDemandPageVo::getRecordStaffName)
                        .queryWrapper(recordStaffName -> queryWrapper.create()
                                .select(STAFF.NAME.as(TaskDemandPageVo::getRecordStaffName))
                                .from(STAFF)
                                .where(STAFF.ID.eq(recordStaffName.getRecordStaffId()))),
                // 更新人员
                item -> item.field(TaskDemandPageVo::getUpdateStaffName)
                        .queryWrapper(updateStaffName -> queryWrapper.create()
                                .select(STAFF.NAME.as(TaskDemandPageVo::getUpdateStaffName))
                                .from(STAFF)
                                .leftJoin(SYS_USER)
                                .on(SYS_USER.ID.eq(STAFF.USER_ID))
                                .where(SYS_USER.ID.eq(updateStaffName.getUpdateUserId()))
                                .and(SYS_USER.USER_TYPE.eq(UserType.OAM_USER.toString()))
                                .limit(1)),
                // 任务接收员工
                item -> item.field(TaskDemandPageVo::getResponsibleStaffName).queryWrapper(responsibleStaffName -> {
                    if (StringUtils.isNotBlank(responsibleStaffName.getResponsibleStaffId())) {
                        return queryWrapper.create()
                                .select(STAFF.NAME.as(TaskDemandPageVo::getResponsibleStaffId))
                                .from(STAFF)
                                .where(STAFF.ID.eq(responsibleStaffName.getResponsibleStaffId()));
                    } else {
                        return null;
                    }
                }));
    }

    /**
     * 工单模块-需求-新增需求
     * @author DB
     * @param bo 请求参数
     * @since 2023-11-30 17:27:24
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertTaskDemand(TaskDemandBo bo) {
        // 添加任务
        Task task = BeanUtils.mapToClass(bo, Task.class);
        // 当前操作员工
        JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo();
        // 默认待审核
        task.setTaskStatus(0).setTaskItem(0).setTaskType(1).setRecordStaffId(loginUserInfo.getString("id")).setSubject("果酱盒子");
        TaskService taskService = SpringUtils.getBean(TaskService.class);
        taskService.save(task);
        // 添加需求
        TaskDemand entity = new TaskDemand();
        BeanUtils.copyBeanProp(entity, bo);
        entity.setTaskId(task.getId());
        this.save(entity);
        // 获取审核管理员手机号
        RedisService redisService = SpringUtils.getBean(RedisService.class);
        CommonService commonService = SpringUtils.getBean(CommonService.class);
        String auditStaffPhone = redisService.getCacheObject(commonService.getCacheKey(OamConfigEnum.AUDIT_STAFF_PHONE.getKey()));
        if (StringUtils.isBlank(auditStaffPhone)) {
            SysConfig sysConfig = SpringUtils.getBean(CoreService.class).selectConfigByKey(commonService.getCacheKey(OamConfigEnum.AUDIT_STAFF_PHONE.getKey()));
            auditStaffPhone = sysConfig.getConfigValue();
            redisService.setCacheObject(commonService.getCacheKey(OamConfigEnum.AUDIT_STAFF_PHONE.getKey()), auditStaffPhone);
        }
        // 企微通知审核管理员
        List<String> phoneList = new ArrayList<String>();
        phoneList.add(auditStaffPhone);
        // 同时通知发起人
        phoneList.add(loginUserInfo.getString("phoneNumber"));
        try {
            SpringUtils.getBean(WebHookSendHandler.class)
                .webHookSendText(WebHookKeyConstant.PRODUCT_BOT,
                    phoneList,
                    "==========您有一条新的需求任务需要审核==========" + "\n" + task.getTaskContent(),
                    false);
        } catch (IOException e) {
            throw new ServiceException("发送需求任务消息通知失败!");
        }
    }

    /**
     * 工单模块-需求-修改需求
     * @author DB
     * @param bo 请求参数
     * @since 2023-11-30 18:26:42
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDemandTask(TaskDemandBo bo) {
        TaskDemand taskDemand = this.getById(bo.getId());
        // 更新需求
        this.updateChain()
            .set(TASK_DEMAND.BRAND_ID, bo.getBrandId())
            .set(TASK_DEMAND.STORE_ID, bo.getStoreId())
            .where(TASK_DEMAND.ID.eq(bo.getId()))
            .update();
        // 更新任务
        SpringUtils.getBean(TaskService.class)
            .updateChain()
            .set(TASK.TASK_CONTENT, bo.getTaskContent())
            .set(TASK.ATTACHMENT_URL, bo.getAttachmentUrl())
            .where(TASK.ID.eq(taskDemand.getTaskId()))
            .update();
    }

    /**
     * 工单模块-需求-删除需求
     * @author DB
     * @param demandId 需求id
     * @since 2023-11-30 20:30:54
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeDemandTask(String demandId) {
        // 获取任务
        TaskDemand demand = this.getById(demandId);
        this.removeById(demandId);
        SpringUtils.getBean(TaskService.class).removeById(demand.getTaskId());
    }

    /**
     * 工单模块-需求-需求加急
     * @author DB
     * @since 2023/12/08
     * @param bo 请求参数
     */
    @Override
    public TaskDemandUrgentVo demandUrgent(TaskDemandUrgentBo bo) {
        //获取需求任务
        TaskDemand demand = this.getById(bo.getId());
        TaskDemandUrgentVo taskDemandUrgentVo = BeanUtils.mapToClass(demand, TaskDemandUrgentVo.class);
        TaskService taskService = SpringUtils.getBean(TaskService.class);
        Task task = taskService.getById(demand.getTaskId());
        taskDemandUrgentVo.setTaskRating(task.getTaskRating());
        if (!task.getIsUrgent()){
            WxMaQrcodeService qrcodeService = SpringUtils.getBean(WxMaService.class).getQrcodeService();
            try {
                // 获取当前执行环境
                String active = SpringUtils.getActiveProfile();
                byte[] qrCodeBytes = qrcodeService.createWxaCodeUnlimitBytes(bo.getId(), "pages/index/index", false, StringUtils.equals(active, "prod") ? "release" : "trial", 430,
                        true, null, false);
                Base64.Encoder encoder = Base64.getEncoder();
                String qrCode = encoder.encodeToString(qrCodeBytes);
                //存在本地
                this.updateChain().set(TASK_DEMAND.PAY_QR_CODE, Constants.QRCODE_HEADER + qrCode)
                        .where(TASK_DEMAND.ID.eq(bo.getId())).update();
                //更新任务
                taskService.updateChain().set(TASK.IS_URGENT,true).where(TASK.ID.eq(demand.getTaskId())).update();
                taskDemandUrgentVo.setPayQrCode(Constants.QRCODE_HEADER + qrCode);
            } catch (WxErrorException e) {
                throw new ServiceException("生成支付码失败");
            }
        }
        return taskDemandUrgentVo;
    }
}
