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


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zfire.jiasm.syncdata.data.Token;
import com.zfire.jiasm.syncdata.plus.entity.ItfGreeToFaRepairSynRule;
import com.zfire.jiasm.syncdata.plus.service.ItfGreeToFaRepairSynRuleService;
import com.zfire.jiasm.syncdata.service.PublicService;
import com.zfire.jiasm.syncdata.service.RepairDownloadService;
import com.zfire.jiasm.syncdata.utils.DataUtil;
import com.zfire.jiasm.syncdata.utils.HttpUtil;
import com.zfire.jiasm.syncdata.utils.JSONResult;
import com.zfire.jiasm.syncdata.utils.TokenCenter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
@Service
public class RepairDownloadServiceImpl implements RepairDownloadService {
    @Value("${baseurl}")
    private String baseurl = "";
    @Value("${nullCols}")
    private String nullCols;
    @Value("${repairdownc}")
    private String repairdownc = "";


    @Autowired
    TokenCenter tokenCenter;
    @Resource
    ItfGreeToFaRepairSynRuleService itfGreeToFaRepairSynRuleService;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    private Set<String> nullDateCols;
    @Resource
    PublicService publicService;



    @Override
    public void processRepairDownload() throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        ItfGreeToFaRepairSynRule synRule = new ItfGreeToFaRepairSynRule();

        try {
            List<ItfGreeToFaRepairSynRule> synRules = itfGreeToFaRepairSynRuleService.lambdaQuery()
                    .orderByAsc(ItfGreeToFaRepairSynRule::getId).list();
            if (CollectionUtils.isEmpty(synRules)){
                return;
            }
            synRule = synRules.get(0);

            log.info("开始下载维修工单: \uF0B7{}",sdf.format(new Date()));

            // 数据源表名
            String srcTabNames = synRule.getSrcTabName();
            String[] srcTabnameArray = srcTabNames.trim().split("\\Q|\\E");

            // 数据源表列
            String srcTabColLists = synRule.getSrcTabColList();
            String[] srcTabColListArray = srcTabColLists.trim().split("\\Q|\\E");

            // 数据目的表名
            String destTabNames = synRule.getDestTabName();
            String[] destTabNameArray = destTabNames.trim().split("\\Q|\\E");

            // 数据目的表列
            String destTabColLists = synRule.getDestTabColList();
            String[] destTabColListArray = destTabColLists.trim().split("\\Q|\\E");

            // 销售公司编码
            String salesWebsitNumber = synRule.getSalesWebsitNumber();
            String downloadBatchNo = publicService.getUUID();
            // 获取数据
            JSONArray datas = downloadData(downloadBatchNo, salesWebsitNumber);

            if (datas !=null){
                log.info("维修工单下载了{}条数据",datas.size());
            }

            for (int i = 0; i < datas.size(); i++) {
                JSONObject sheet = datas.getJSONObject(i);
                try{
                    // 维修工单主表必须存在
                    JSONObject mainTableData = sheet.getJSONObject("tblAssign");
                    if (mainTableData != null) {
                        String downloadTaskNo = publicService.getUUID();
                        DataUtil.initLastModifiedDate(mainTableData,"last_modified_date");
                        addRepairData(mainTableData, downloadBatchNo, downloadTaskNo, sheet,
                                srcTabnameArray, srcTabColListArray, destTabNameArray, destTabColListArray,
                                salesWebsitNumber);
                    } else {
                        log.error("维修工单找不到主表数据,downloadBatchNo[" + downloadBatchNo + "]");
                    }
                } catch (Exception ex) {
                    log.info("维修工单下载落download表失败：{}" ,JSONObject.toJSONString(sheet));
                    ex.printStackTrace();
                }


            }

            datas.clear();

            log.info("维修工单同步下载状态");
            // 与总部同步下载状态，修改本地下载记录表状态 gree_stat_syn_status =1
            updateStatus();

            log.info("维修工单下载完成");
        } catch (Exception ex) {
            log.error("从总部取维修工单失败", ex);
        }

    }


    private void updateStatus() {
        try {
            List<Map<String, Object>> result = getNeedUpdateTaskData("itf_repair_batch_download_rec");
            Token token = tokenCenter.getCurrentToken();
            String url = baseurl + "tblAssign" + "/updateExtjson5";
            for (Map<String, Object> row : result) {
                Long synReqId = (Long) row.get("syn_req_id");

                try {
                    String pgid = row.get("pgid").toString();
                    Date lastModifiedDate = (Date) row.get("last_modified_date");

                    Map<String, Object> paramMap = new HashMap<String, Object>();
                    paramMap.put("pgid", pgid);
                    paramMap.put("lastModifiedDate", lastModifiedDate);

                    JSONResult jsonResult = HttpUtil.httpRequestWithToken(url, "POST",
                            JSON.toJSONStringWithDateFormat(paramMap, "yyyy-MM-dd HH:mm:ss"), token);

                    if (jsonResult.isOK()) {
                        updateSuccess(synReqId, "itf_repair_batch_download_rec");
                    } else {
                        updateError(synReqId, jsonResult.getMsg(), "itf_repair_batch_download_rec");
                    }
                } catch (Exception ex) {
                    log.error("ES更新维修主表下载状态失败syn_req_id=" + synReqId, ex);
                    updateError(synReqId, ex.getMessage(), "itf_repair_batch_download_rec");
                }
            }
        } catch (Exception ex) {
            log.error("ES更新维修主表下载状态失败", ex);
        }
    }

    public void updateError(Long synReqId, String errorMessage, String tabName) {
        jdbcTemplate.update(
                "update " + tabName + " set gree_stat_syn_status=99,gree_stat_syn_err_msg=? where syn_req_id=?",
                new Object[] { errorMessage, synReqId });
    }

    public void updateSuccess(Long synReqId, String tabName) {
        jdbcTemplate.update("update " + tabName + " set gree_stat_syn_status=1,gree_stat_syn_time=? where syn_req_id=?",
                new Object[] { new Date(System.currentTimeMillis()), synReqId });
    }

    public List<Map<String, Object>> getNeedUpdateTaskData(String tabName) {
        List<Map<String, Object>> result = jdbcTemplate
                .queryForList("SELECT * from " + tabName + " where gree_stat_syn_status=0 order by syn_req_id ");
        return result;
    }

    private JSONArray downloadData(String downloadBatchNo, String salesWebsitNumber) throws Exception {

        Token token = tokenCenter.getCurrentToken();
        String url = baseurl + "api/repair/batchsearch/repairorders?ssxsgs=" + salesWebsitNumber;
        // log.info("url[" + url + "],downloadBatchNo[" + downloadBatchNo + "],send[]");
        JSONObject jsonResult = HttpUtil.httpRequestGetPgid(url, "GET", token, downloadBatchNo,null);

        String statusCode = jsonResult.getString("statusCode");
        if ("200".equals(statusCode)) {
            JSONArray datas = jsonResult.getJSONArray("data");
            return datas;
        } else {
            String errorMessage = jsonResult.getString("message");
            if (errorMessage == null || errorMessage.trim().length() == 0) {
                errorMessage = "失败";
            }
            throw new Exception(errorMessage);
        }

    }

    @Transactional(rollbackFor = Exception.class)
    public void addRepairData(JSONObject mainTableData, String downloadBatchNo, String downloadTaskNo, JSONObject sheet,
                              String[] srcTabnameArray, String[] srcTabColListArray, String[] destTabNameArray,
                              String[] destTabColListArray, String salesWebsitNumber) throws Exception {
        // 查看同一时间同一工单是否存在下载记录表 存在不再保存本次的同步数据
        if (insertRepairRecData(mainTableData, downloadBatchNo, downloadTaskNo, salesWebsitNumber)) {
            parseData(sheet, srcTabnameArray, srcTabColListArray, destTabNameArray, destTabColListArray, downloadTaskNo,
                    false, downloadBatchNo);
        }
    }

    private boolean insertRepairRecData(JSONObject aData, String downloadBatchNo, String downloadTaskNo,
                                        String salesWebsitNumber) throws Exception {

        // 查看 相同时间同一单数据
        List<Map<String, Object>> rec = isRepairDuplicate(aData);


        boolean duplicate = (rec.size() > 0);

        String sql = "insert into itf_repair_batch_download_rec (sales_websit_number,download_batch_no,download_task_no,"
                + "created_by,created_date,last_modified_by,last_modified_date,pgid,"
                + "extjson1,extjson2,extjson3,extjson4,extjson5" + (duplicate ? ",gree_stat_syn_err_msg" : "")
                + ") values (" + "?,?,?,?,?,?,?,?,?,?,?,?,?" + (duplicate ? ",?" : "") + ") ";

        // 存在 说明重复获取，不再保存数据
        if (duplicate) {
            if (!recHasNoUploadStatus(rec)) {
                jdbcTemplate.update(sql,
                        new Object[] { salesWebsitNumber, downloadBatchNo, downloadTaskNo,
                                aData.getString("created_by"), aData.getString("created_date"),
                                aData.getString("last_modified_by"), aData.getString("last_modified_date"),
                                aData.getString("pgid"), aData.getString("extjson1"), aData.getString("extjson2"),
                                aData.getString("extjson3"), aData.getString("extjson4"), aData.getString("extjson5"),
                                "任务已经存在，不再产生下载数据" });
            }
            return false;
        } else {
            jdbcTemplate.update(sql,
                    new Object[] { salesWebsitNumber, downloadBatchNo, downloadTaskNo, aData.getString("created_by"),
                            aData.getString("created_date"), aData.getString("last_modified_by"),
                            aData.getString("last_modified_date"), aData.getString("pgid"), aData.getString("extjson1"),
                            aData.getString("extjson2"), aData.getString("extjson3"), aData.getString("extjson4"),
                            aData.getString("extjson5") });
            return true;
        }

    }

    private List<Map<String, Object>> isRepairDuplicate(JSONObject aData) throws DataAccessException, ParseException {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        List<Map<String, Object>> result = jdbcTemplate.queryForList(
                "select * from itf_repair_batch_download_rec where pgid=? and last_modified_date=?",
                new Object[] { aData.getString("pgid"), sdf.parse(aData.getString("last_modified_date")) });

        return result;
    }

    private boolean recHasNoUploadStatus(List<Map<String, Object>> rec) {
        for (Map<String, Object> data : rec) {
            int greeStatSynStatus = (Integer) data.get("gree_stat_syn_status");
            if (greeStatSynStatus == 0) {
                return true;
            }
        }
        return false;
    }

    private void parseData(JSONObject sheet, String[] srcTabnameArray, String[] srcTabColListArray,
                           String[] destTabNameArray, String[] destTabColListArray, String downloadTaskNo, boolean isInstall,
                           String downloadBatchNo) throws Exception {

        for (int i = 0; i < srcTabnameArray.length; i++) {

            String srcTabname = srcTabnameArray[i];
            String srcTabColList = srcTabColListArray[i];
            String destTabName = destTabNameArray[i];
            String destTabColList = destTabColListArray[i];

            String[] arySrcTabCol = srcTabColList.split("\\Q,\\E");

            JSONArray tableData = new JSONArray();

            if (isInstall) {
                tableData = sheet.getJSONArray(srcTabname.toUpperCase());
            } else {
                if ("tblAssign".equalsIgnoreCase(DataUtil.fromDbName2ServiceName(srcTabname))) {
                    tableData = new JSONArray();
                    tableData.add(sheet.getJSONObject("tblAssign"));
                } else {
                    tableData = sheet.getJSONArray(DataUtil.fromDbName2ServiceName(srcTabname));
                }

            }

            if (tableData == null){
                continue;
            }

            for (int j = 0; j < tableData.size(); j++) {
                parseAData(isInstall, downloadBatchNo, downloadTaskNo, destTabName, destTabColList, arySrcTabCol,
                        tableData.getJSONObject(j));
            }
        }
    }

    public void parseAData(boolean isInstall, String downloadBatchNo, String downloadTaskNo, String destTabName,
                           String destTabColList, String[] arySrcTabCol, JSONObject aData) throws Exception {
        String table = "itf_tbl_az_assign_platform_download";
        String daijian = "itf_tbl_assign_daijian_download";
        String yd = "itf_tbl_assign_xzyd_download";

        String[] arySrcTabColValue = new String[arySrcTabCol.length];

        for (int j = 0; j < arySrcTabCol.length; j++) {
            if (isInstall) {
                if (destTabName.equals(table) && (j==2 || j== 4 || j==9)){
                    if (StringUtils.isEmpty(DataUtil.findValue(DataUtil.fromDbName2ServiceName(arySrcTabCol[j].trim()),aData))){
                        arySrcTabColValue[j] = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                        continue;
                    }
                }
                arySrcTabColValue[j] = DataUtil.findValue(DataUtil.fromDbName2ServiceName(arySrcTabCol[j].trim()),
                        aData);
            } else {
                if (destTabName.equals(daijian)){
                    //创建时间 cjdt
                    DataUtil.initLastModifiedDate(aData,"cjdt");
                    // 商品大类 splb
                    DataUtil.initOther(aData,"splb");
                    // 替换编码销售公司库存 thbmxsgsnum
                    DataUtil.initOther(aData,"thbmxsgsnum");
                    // 替换编码区域库存 thbmqynum
                    DataUtil.initOther(aData,"thbmqynum");
                    // 替换编码网点库存 thbmwdnum
                    DataUtil.initOther(aData,"thbmwdnum");
                    // 配件系统处理标识 pjxtflag
                    DataUtil.initOther(aData,"pjxtflag");
                    // 区域配件库存 djquyunum
                    DataUtil.initOther(aData,"djquyunum");
                    // 销售公司配件库存 djxsgsnum
                    DataUtil.initOther(aData,"djxsgsnum");
                    // 网点配件库存 djwdnum
                    DataUtil.initOther(aData,"djwdnum");
                } else if (destTabName.equals(yd)){
                    DataUtil.initOther(aData,"cshu");
                    DataUtil.initOther(aData,"ydbz");
                }

                String colName = arySrcTabCol[j].trim();
                arySrcTabColValue[j] = DataUtil.findValue(colName, aData);
                if (getNullColSet().contains(colName)) {
                    if ("".equals(arySrcTabColValue[j])) {
                        arySrcTabColValue[j] = null;
                    }
                }
            }
        }

        insertAData(downloadBatchNo, downloadTaskNo, destTabName, destTabColList, arySrcTabColValue);
    }

    public void insertAData(String downloadBatchNo, String downloadTaskNo, String destTabName, String destTabColList,
                            Object[] arySrcTabColValue) throws Exception {

        StringBuffer mark = new StringBuffer();
        for (int i = 0; i < arySrcTabColValue.length; i++) {
            if (mark.length() > 0) {
                mark.append(",");
            }
            mark.append("?");
        }

        String sql = "insert into " + destTabName + " (download_batch_no,download_task_no," + destTabColList
                + ") values (?,?," + mark + ") ";

        Object[] insertValue = new Object[arySrcTabColValue.length + 2];
        insertValue[0] = downloadBatchNo;
        insertValue[1] = downloadTaskNo;
        System.arraycopy(arySrcTabColValue, 0, insertValue, 2, arySrcTabColValue.length);
        jdbcTemplate.update(sql, insertValue);

    }

    private synchronized Set<String> getNullColSet(){
        if(nullDateCols==null) {
            nullDateCols=new HashSet<String>();
            String[] nullColArray=nullCols.split("\\Q,\\E");
            for(String value:nullColArray) {
                nullDateCols.add(value);
            }
        }
        return nullDateCols;
    }



}
