package com.zfire.jiasm.syncdata.service.impl;

import com.zfire.jiasm.syncdata.constant.GDOrderStatusEnum;
import com.zfire.jiasm.syncdata.constant.OrderTypeEnum;
import com.zfire.jiasm.syncdata.constant.SynStatusEnum;
import com.zfire.jiasm.syncdata.plus.entity.*;
import com.zfire.jiasm.syncdata.plus.service.*;
import com.zfire.jiasm.syncdata.service.InstallProduceUploadListService;
import com.zfire.jiasm.syncdata.service.PrepareService;
import com.zfire.jiasm.syncdata.service.PublicService;
import com.zfire.jiasm.syncdata.utils.DataUtil;
import com.zfire.jiasm.syncdata.utils.PrepareTaskLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Service
public class InstallProduceUploadListServiceImpl implements InstallProduceUploadListService {
    @Value("${azuploadscc}")
    private String azuploadscc = "";

    @Resource
    PrepareService prepareService;
    @Resource
    OutJiasmToGreeUploadTaskListService outJiasmToGreeUploadTaskListService;
    @Resource
    OrderBaseService orderBaseService;
    @Resource
    OutJiasmToGreeUploadnotifylistService outJiasmToGreeUploadnotifylistService;
    @Resource
    OrderInstallOperatingLogService orderInstallOperatingLogService;
    @Resource
    OrderReAppointmentService orderReAppointmentService;
    @Resource
    PublicService publicService;
    @Resource
    OrderProductService orderProductService;
    @Resource
    OrderInformationService orderInformationService;
    @Resource
    TestService testService;



    @Override
    public void processUploadList() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<OutJiasmToGreeUploadnotifylist> taskResults = new ArrayList<>();
        List<OutJiasmToGreeUploadTaskList> ojtgutls = new ArrayList<>();
        log.info("开始预处理需要上传的工单数据: \uF0B7{}",sdf.format(new Date()));

        //测试使用
        List<String> orderNos = new ArrayList<>();
        List<Test> orderno = testService.lambdaQuery()
                .eq(Test::getFlag,1).list();
        if (CollectionUtils.isEmpty(orderno)){
            return;
        }
        orderno.stream().forEach(event->{
            orderNos.add(event.getId());
        });
        orderno.clear();




        // 从需要上传的订单数据表中提取数据
        taskResults = outJiasmToGreeUploadnotifylistService.lambdaQuery()
                .eq(OutJiasmToGreeUploadnotifylist::getSynStatus, SynStatusEnum.UN_SYN.getCode())
                // .eq(OutJiasmToGreeUploadnotifylist::getSynReqId, 20916)// 测试用
                .in(OutJiasmToGreeUploadnotifylist::getOrderNo, orderNos)// 测试用
                .orderByAsc(OutJiasmToGreeUploadnotifylist::getSynReqId)
                .list();
        try {
            for (OutJiasmToGreeUploadnotifylist item : taskResults) {
                // 同步的表名
                String itemTableName = item.getTableName();
                // 同步表中的工单号
                String itemOrderNo = item.getOrderNo();
                // 同步表中的主键id
                String itemTableNameId = item.getId();
                String itemOrderType = item.getOrderType();

                // 数据同步预处理规则表中提取对应表名的规则
                Map<String, Object> row = prepareService.getTaskInfo(itemTableName);
                int taskId = (Integer) row.get("id");
                String srcTabName = (String) row.get("src_tab_name");

                String errorMessage = null;
                try {
                    // 根据表名获取表中指定工单的数据
                    // 规则表中表名，同步表中的单号，同步表中的id(同步表中的表名的主键)
                    // Map<String, Object> sourceData = prepareService.getTaskDataDetail(srcTabName, orderNo,topOrderId);

                    // 过程名，规则表中的ID，源表中的数据最后修改时间，需同步的表中的工单号，需同步的表中的主键id,空值，false
                    // prepareService.prepareData(procName, taskId, date, sOrderNo, orderId, newDykh, isNeedGenRemoteId);
                    // 工单表执行 TL_PrePare_task_by_fa_order_install 过程

                    // 数据上传任务表OutJiasmToGreeUploadTaskList 生成数据

                    // 安装工单处理 22,221,222
                    if (itemTableName.equals("order_base") &&
                            itemOrderType.equals(OrderTypeEnum.ORDER_TYPE_INSTALL.getCode())){
                        orderBaseProess(itemTableNameId, ojtgutls, item.getSynReqId(), itemTableName, itemOrderType);
                    }
                    // 安装工单操作日志 23
                    if (itemTableName.equals("order_install_operating_log")){
                        orderInstallOperatingLog(item, itemTableName, itemOrderType);
                    }
                    // 安装工单用户预约、改约明细 230 同时向发短信表插入一条数据
                    if (itemTableName.equals("order_re_appointment") &&
                            itemOrderType.equals(OrderTypeEnum.ORDER_TYPE_INSTALL.getCode())){
                        OrderReAppointment(item, itemTableName, itemOrderType);
                    }
                    // 安装工单产品信息 24
                    if (itemTableName.equals("order_product") &&
                            itemOrderType.equals(OrderTypeEnum.ORDER_TYPE_INSTALL.getCode())){
                        // TL_PrePare_task_by_fa_order_install_product 24
                        orderProductProess(item, itemTableName, itemOrderNo, itemTableNameId);
                    }
                    // 安装工单子信息  26
                    if (itemTableName.equals("order_information") &&
                            itemOrderType.equals(OrderTypeEnum.ORDER_TYPE_INSTALL.getCode())){
                        // TL_PrePare_task_by_fa_order_install_information
                        orderInformationProess(item, itemTableName, itemOrderNo, itemTableNameId);
                    }
                } catch (Exception ex) {
                    errorMessage = ex.getMessage();
                    updateError(errorMessage, item);
                } finally {
                    PrepareTaskLog.writeMessage(genInfoData(taskId, srcTabName, false, errorMessage));
                }
            }
            log.info("预处理需要上传的安装工单数据完成: \uF0B7{}",sdf.format(new Date()));
        } catch (Exception ex) {
            ex.printStackTrace();
            log.info("开始预处理需要上传的工单数据出错");
        }
    }


    @Transactional(rollbackFor = Exception.class)
    public void orderInformationProess(OutJiasmToGreeUploadnotifylist item, String itemTableName, String itemOrderNo, String itemTableNameId) {
        // 提取对应的子信息
        OrderInformation oi = orderInformationService.lambdaQuery()
                .eq(OrderInformation::getId, itemTableNameId).one();
        if (oi!=null){
            // 生成26类型上传任务数据
            // 单号，主键，同步任务生成时间，同步的表名，工单类型，任务类型
            OutJiasmToGreeUploadTaskList add = publicService.getUploadTaskList(itemOrderNo, itemTableNameId,oi.getUpdateTime(), itemTableName,
                    OrderTypeEnum.ORDER_TYPE_INSTALL.getCode(),26);
            outJiasmToGreeUploadTaskListService.save(add);

        }


        // 需要上传的订单数据表中处理状态同步为已处理
        OutJiasmToGreeUploadnotifylist upn = getOutJiasmToGreeUploadnotifylist(item.getSynReqId());
        outJiasmToGreeUploadnotifylistService.updateById(upn);
    }

    @Transactional(rollbackFor = Exception.class)
    public void orderProductProess(OutJiasmToGreeUploadnotifylist item, String itemTableName, String itemOrderNo, String itemTableNameId) {
        // 提取工单机型
        OrderProduct op = orderProductService.lambdaQuery()
                .eq(OrderProduct::getId, itemTableNameId).one();
        if (op!=null){
            // 生成24类型上传任务数据
            // 单号，主键，同步任务生成时间，同步的表名，工单类型，任务类型
            OutJiasmToGreeUploadTaskList add = publicService.getUploadTaskList(itemOrderNo, itemTableNameId,op.getUpdateTime(), itemTableName,
                    OrderTypeEnum.ORDER_TYPE_INSTALL.getCode(),24);
            outJiasmToGreeUploadTaskListService.save(add);
        }

        // 需要上传的订单数据表中处理状态同步为已处理
        OutJiasmToGreeUploadnotifylist upn = getOutJiasmToGreeUploadnotifylist(item.getSynReqId());
        outJiasmToGreeUploadnotifylistService.updateById(upn);
    }

    @Transactional(rollbackFor = Exception.class)
    public  void OrderReAppointment(OutJiasmToGreeUploadnotifylist item, String itemTableName, String itemOrderType) {
        OrderReAppointment rea = orderReAppointmentService.lambdaQuery()
                .eq(OrderReAppointment::getId, item.getId()).one();
        // 同步任务增加一条数据
        if (rea !=null){
            OutJiasmToGreeUploadTaskList add = publicService.getUploadTaskList(item.getOrderNo(), item.getId(),
                    rea.getCreateTime(), itemTableName, itemOrderType, 230);
            outJiasmToGreeUploadTaskListService.save(add);
            // 向发短信表插入一条数据，短信表ID同预约改约表ID相同 平台插入同步服务不再操作
            // publicService.addFaOrderSms(rea);
        }

        // 需要上传的订单数据表中处理状态同步为已处理
        OutJiasmToGreeUploadnotifylist up = getOutJiasmToGreeUploadnotifylist(item.getSynReqId());
        outJiasmToGreeUploadnotifylistService.updateById(up);
    }

    @Transactional(rollbackFor = Exception.class)
    public void orderInstallOperatingLog(OutJiasmToGreeUploadnotifylist item, String itemTableName, String itemOrderType) {
        OrderInstallOperatingLog logInfo = orderInstallOperatingLogService.lambdaQuery()
                .eq(OrderInstallOperatingLog::getId, item.getId()).one();
        // 同步任务增加一条数据
        if (logInfo !=null){
            OutJiasmToGreeUploadTaskList add = publicService.getUploadTaskList(item.getOrderNo(), item.getId(),
                    logInfo.getCreateTime(), itemTableName, itemOrderType, 23);
            outJiasmToGreeUploadTaskListService.save(add);
        }

        // 需要上传的订单数据表中处理状态同步为已处理
        OutJiasmToGreeUploadnotifylist up = getOutJiasmToGreeUploadnotifylist(item.getSynReqId());
        outJiasmToGreeUploadnotifylistService.updateById(up);
    }


    public void updateError(String errMessage, OutJiasmToGreeUploadnotifylist item) {
        if (errMessage != null && errMessage.trim().length() > 255) {
            errMessage = errMessage.substring(0, 255);
        }
        OutJiasmToGreeUploadnotifylist up = new OutJiasmToGreeUploadnotifylist();
        up.setSynReqId(item.getSynReqId());
        up.setSynTimes(item.getSynTimes()+1);
        up.setSynErrMsg(errMessage);
        up.setSynReqTime(new Date());
        outJiasmToGreeUploadnotifylistService.updateById(up);
    }

    @NotNull
    private OutJiasmToGreeUploadnotifylist getOutJiasmToGreeUploadnotifylist(Long synReqId) {
        OutJiasmToGreeUploadnotifylist up = new OutJiasmToGreeUploadnotifylist();
        up.setSynReqId(synReqId);
        up.setSynStatus(1);
        up.setSynReqTime(new Date());
        return up;
    }


    @Transactional(rollbackFor = Exception.class)
    public void orderBaseProess(String itemTableNameId, List<OutJiasmToGreeUploadTaskList> ojtgutls, Long synReqId, String itemTableName, String itemOrderType) {
        OrderBase orderBase = orderBaseService.lambdaQuery()
                .eq(OrderBase::getId,itemTableNameId).one();

        // 安装工单处理
        if (orderBase !=null){
            InstallOrderBase(itemTableNameId, orderBase.getUpdateTime(), orderBase, ojtgutls, itemTableName, itemOrderType);
        }

        if (ojtgutls.size()>0){
            outJiasmToGreeUploadTaskListService.saveBatch(ojtgutls);
            ojtgutls.clear();
        }
        // 需要上传的订单数据表中处理状态同步为已处理
        OutJiasmToGreeUploadnotifylist up = getOutJiasmToGreeUploadnotifylist(synReqId);
        outJiasmToGreeUploadnotifylistService.updateById(up);
    }

    private void InstallOrderBase(String orderNo, Date updateTime, OrderBase orderBase, List<OutJiasmToGreeUploadTaskList> ojtgutls,
                                  String itemTableName, String itemOrderType) {
        // 若工单被删除不再同步 不写上传记录表

        // 生成一条22类型的上传记录  out_jiasm_to_gree_upload_task_list
        OutJiasmToGreeUploadTaskList add = publicService.getUploadTaskList(orderNo, orderBase.getId(), updateTime, itemTableName, itemOrderType, 22);
        ojtgutls.add(add);
        // 工单状态order_status 6, 7, 9, 10
        if (orderBase.getOrderStatus().equals(GDOrderStatusEnum.INSTALL_STATUS_G6.getCode()) ||
                orderBase.getOrderStatus().equals(GDOrderStatusEnum.INSTALL_STATUS_G7.getCode()) ||
                orderBase.getOrderStatus().equals(GDOrderStatusEnum.INSTALL_STATUS_G9.getCode()) ||
                orderBase.getOrderStatus().equals(GDOrderStatusEnum.INSTALL_STATUS_G10.getCode())){
            if (orderBase.getOrderStatus().equals(GDOrderStatusEnum.INSTALL_STATUS_G6.getCode())){
                OutJiasmToGreeUploadTaskList addo = publicService.getUploadTaskList(orderNo, orderBase.getId(),
                        updateTime, itemTableName, itemOrderType, 221);
                ojtgutls.add(addo);
            } else if (orderBase.getOrderStatus().equals(GDOrderStatusEnum.INSTALL_STATUS_G7.getCode()) ||
                    orderBase.getOrderStatus().equals(GDOrderStatusEnum.INSTALL_STATUS_G9.getCode())){
                OutJiasmToGreeUploadTaskList addt = publicService.getUploadTaskList(orderNo, orderBase.getId(),
                        updateTime, itemTableName, itemOrderType, 221);
                ojtgutls.add(addt);
                OutJiasmToGreeUploadTaskList addtt = publicService.getUploadTaskList(orderNo, orderBase.getId(),
                        orderBase.getUpdateTime(), itemTableName, itemOrderType, 222);
                ojtgutls.add(addtt);
            } else {
                OutJiasmToGreeUploadTaskList addttt = publicService.getUploadTaskList(orderNo, orderBase.getId(),
                        updateTime, itemTableName, itemOrderType, 222);
                ojtgutls.add(addttt);
            }
        }
    }


    private String genInfoData(int taskId, String srcTabName, boolean isTimeOut, String errorMessage) {
        String result = "预处理任务[" + taskId + "," + srcTabName + "] " + (isTimeOut ? "超时!!!!" : "正常") + " "
                + (errorMessage != null ? "错误:[" + errorMessage + "]" : "");
        return result;
    }

    private Map<String, Object> genDataMapFromSource(String localKeyList, String serverKeyList,
                                                     Map<String, Object> sourceData) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        String[] localKeys = localKeyList.split("\\Q,\\E");
        String[] serverKeys = serverKeyList.split("\\Q,\\E");
        for (int i = 0; i < localKeys.length; i++) {
            String localKey = localKeys[i];
            String serverKey = serverKeys[i];
            Object value = sourceData.get(localKey.trim());
            paramMap.put(DataUtil.fromDbName2ServiceName(serverKey.trim()), value);
        }

        return paramMap;
    }
}
