package com.yeejoin.amos.patrol.business.data;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.amos.boot.biz.common.utils.SnowflakeIdUtil;
import com.yeejoin.amos.component.robot.AmosRequestContext;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.patrol.business.constants.XJConstant;
import com.yeejoin.amos.patrol.business.dao.mapper.CheckInputMapper;
import com.yeejoin.amos.patrol.business.dao.mapper.CheckMapper;
import com.yeejoin.amos.patrol.business.dao.mapper.PlanTaskDetailMapper;
import com.yeejoin.amos.patrol.business.dao.mapper.PlanTaskMapper;
import com.yeejoin.amos.patrol.business.dao.repository.IInputItemDao;
import com.yeejoin.amos.patrol.business.dao.repository.IPlanTaskDao;
import com.yeejoin.amos.patrol.business.dao.repository.IPlanTaskDetailDao;
import com.yeejoin.amos.patrol.business.dto.CheckRecordDataDto;
import com.yeejoin.amos.patrol.business.entity.mybatis.PlanTaskPointInputItemBo;
import com.yeejoin.amos.patrol.common.enums.CheckStatusEnum;
import com.yeejoin.amos.patrol.common.enums.PlanTaskDetailIsFinishEnum;
import com.yeejoin.amos.patrol.common.enums.PlanTaskDetailStatusEnum;
import com.yeejoin.amos.patrol.dao.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.context.RequestContextModel;

import java.util.*;
import java.util.concurrent.BlockingQueue;

/**
 * @author Administrator
 */
@Slf4j
public class CheckRecordDataConsumer implements Runnable {

    private BlockingQueue<CheckRecordDataDto> blockingQueue;

    private ApplicationContext applicationContext;

    private IPlanTaskDao iPlanTaskDao;

    private PlanTaskMapper planTaskMapper;

    private IPlanTaskDetailDao iPlanTaskDetailDao;

    private IInputItemDao inputItemDao;

    private PlanTaskDetailMapper planTaskDetailMapper;

    private AmosRequestContext requestContext;

    private SnowflakeIdUtil sequence;

    private CheckMapper checkMapper;

    private CheckInputMapper checkInputMapper;


    public CheckRecordDataConsumer(BlockingQueue<CheckRecordDataDto> blockingQueue, ApplicationContext applicationContext) {
        this.blockingQueue = blockingQueue;
        this.applicationContext = applicationContext;
        planTaskMapper = applicationContext.getBean(PlanTaskMapper.class);
        iPlanTaskDao = applicationContext.getBean(IPlanTaskDao.class);
        iPlanTaskDetailDao = applicationContext.getBean(IPlanTaskDetailDao.class);
        inputItemDao = applicationContext.getBean(IInputItemDao.class);
        planTaskDetailMapper = applicationContext.getBean(PlanTaskDetailMapper.class);
        requestContext = applicationContext.getBean(AmosRequestContext.class);
        sequence = applicationContext.getBean(SnowflakeIdUtil.class);
        checkMapper = applicationContext.getBean(CheckMapper.class);
        checkInputMapper = applicationContext.getBean(CheckInputMapper.class);
    }

    @Override
    public void run() {
        while (true) {
            try {
                CheckRecordDataDto checkRecordDataDto = blockingQueue.take();
                this.setRequestContext();
                this.save2Db(checkRecordDataDto);
            } catch (Exception e) {
                log.error("入库失败", e);
            } finally {
                RequestContext.clean();
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void save2Db(CheckRecordDataDto checkRecordDataDto){
        iPlanTaskDao.saveAll(checkRecordDataDto.getPlanTasks());
        iPlanTaskDetailDao.saveAll(checkRecordDataDto.getPlanTaskDetails());
        AgencyUserModel agencyUserModel = this.getAgencyUserModel(checkRecordDataDto.getRequestContextModel());
        createCheckRecord(checkRecordDataDto.getPlanTasks(), agencyUserModel);
        this.updateTaskDetail(checkRecordDataDto.getPlanTaskDetails(), checkRecordDataDto.getRequestContextModel().getExcutedUserId());
    }

    private AgencyUserModel getAgencyUserModel(RequestContextModel requestContextModel) {
        // 记录暂时不用 注释掉
        //List<AgencyUserModel> agencyUserModels = FeignUtil.remoteCall(()->Privilege.agencyUserClient.queryByIds(requestContextModel.getExcutedUserId(),false));
       // return agencyUserModels.get(0);
        return null;
    }

    private void setRequestContext(){
        RequestContext.setAppKey(requestContext.getAppKey());
        RequestContext.setProduct(requestContext.getProduct());
        RequestContext.setToken(requestContext.getToken());
    }

    public void updateTaskDetail(List<PlanTaskDetail> planTaskDetails, String userId) {
        planTaskDetails.forEach(planTaskDetail -> {
            planTaskDetailMapper.finishTaskDetail(planTaskDetail.getId(), planTaskDetail.getPointId(), planTaskDetail.getTaskNo(), userId);
        });
    }


    /**
     * 创建检查记录
     *
     * @param planTasks       任务主表
     * @param agencyUserModel 用户
     */
    public void createCheckRecord(List<PlanTask> planTasks, AgencyUserModel agencyUserModel) {
        List<Check> checks = new ArrayList<>();
        List<CheckInput> checkInputs = new ArrayList<>();
        planTasks.forEach(planTask -> {
            List<PlanTaskPointInputItemBo> planTaskPointInputItems = planTaskMapper.getPlanTaskPointInputItemByPlanTaskId(planTask.getId(), PlanTaskDetailStatusEnum.QUALIFIED.getValue(), Objects.toString(PlanTaskDetailIsFinishEnum.UNFINISHED.getValue()));
            Map<Long, Check> checkMap = new HashMap<>();
            Map<String, String> deptMap = new HashMap<>();
            StringBuffer deptName = new StringBuffer();
            StringBuffer deptId = new StringBuffer();
            StringBuffer userName = new StringBuffer();
            if (planTask.getUserDept().indexOf(",") > 0) {
                List<String> depts = Arrays.asList(planTask.getUserDept().split(","));
                depts.stream().forEach(dept -> {
                    deptMap.put(dept.split("@")[0], dept.split("@")[2]);
                    deptName.append(dept.split("@")[2]).append(",");
                    deptId.append(dept.split("@")[0]).append(",");
                });
                Set<String> departmentOrgCode = new HashSet<>();
                for (String key : deptMap.keySet()) {
                    departmentOrgCode.add(deptMap.get(key));
                }
                StringBuffer deptIds = new StringBuffer();
                Iterator it = departmentOrgCode.iterator();
                while (it.hasNext()) {
                    deptIds.append(it.next()).append(",");
                }
                String realNames = "";
                if (agencyUserModel != null) {
                    realNames = agencyUserModel.getRealName().join(",");
                    userName.append(realNames);
                }
            }
            for (PlanTaskPointInputItemBo arg : planTaskPointInputItems) {
                Check check = new Check();
                if (checkMap.get(arg.getPointId()) == null) {
                    check.setOrgCode(arg.getOrgCode());
                    check.setUserId(planTask.getUserId());
                    int len = userName.toString().indexOf(",");
                    if (len != -1) {
                        check.setUserName(userName.toString());
                    } else {
                        check.setUserName(userName.toString());
                    }

                    check.setDepName(deptName.toString());
                    check.setPointId(arg.getPointId());

                    check.setPointName(arg.getPointName());
                    check.setRouteName(arg.getRouteName());
                    check.setPlanName(arg.getPlanName());
                    check.setErrorClassify(arg.getClassifyName());

                    check.setUploadTime(new Date());
                    check.setPlanId(arg.getPlanId());
                    check.setPlanTaskId(arg.getPlanTaskId());
                    check.setPlanTaskDetailId(arg.getPlanTaskDetailId());
                    check.setRouteId(arg.getRouteId());
                    check.setCheckTime(arg.getEndTime());
                    check.setIsOk(CheckStatusEnum.QUALIFIED.getCode());
                    long checkId = sequence.nextId();
                    check.setId(checkId);
                    checks.add(check);
                    checkMap.put(arg.getPointId(), check);
                } else {
                    check = checkMap.get(arg.getPointId());
                }
                if (arg.getInputItemId() != null) {

                    InputItem inputItem = inputItemDao.findById(arg.getInputItemId()).get();
                    CheckInput checkInput = new CheckInput();

                    if (XJConstant.INPUT_ITEM_SELECT.equals(inputItem.getItemType())) {
                        checkInput = paraseSelect(checkInput, inputItem.getDataJson());
                    } else if (XJConstant.INPUT_ITEM_NUMBER.equals(inputItem.getItemType())) {
                        checkInput.setInputValue(inputItem.getDefaultValue());
                    } else if (XJConstant.INPUT_ITEM_TEXT.equals(inputItem.getItemType())) {
                        checkInput.setInputValue(inputItem.getDefaultValue());
                    }
                    checkInput.setCheckId(check.getId());
                    checkInput.setInputId(arg.getInputItemId());
                    checkInput.setIsOk(CheckStatusEnum.QUALIFIED.getCode());
                    checkInput.setRoutePointItemId(arg.getRoutePointItemId());
                    checkInput.setOrderNo(arg.getOrderNo());
                    checkInput.setOrgCode(arg.getOrgCode());
                    checkInput.setInputName(arg.getInputName());
                    checkInput.setPointClassifyId(arg.getClassifyId());
                    checkInput.setPointClassifyName(arg.getClassifyName());
                    checkInput.setId(sequence.nextId());
                    checkInputs.add(checkInput);
                }

            }
        });
        checkMapper.insertBatch(checks);
        checkInputMapper.insertBatch(checkInputs);
    }

    private CheckInput paraseSelect(CheckInput checkInput, String json) {
        JSONArray jsonArray = JSONArray.parseArray(json);
        if (!ObjectUtils.isEmpty(jsonArray)) {
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                String validateName = jsonObject.getString("name");
                String validateIsOk = jsonObject.getString("isOk");
                if (validateIsOk.equals("是")) {
                    checkInput.setInputValue(validateName);
                }
            }
        }
        return checkInput;
    }
}
