package com.uas.eis.serviceImpl;

import com.uas.eis.dao.*;
import com.uas.eis.entity.EdiSuccessLog;
import com.uas.eis.service.StockService;
import com.uas.eis.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * Created by luhg on 2018/4/19.
 * 出入库相关
 */
@Service
public class StockServiceImpl implements StockService{
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final String sendStockToYundingUrl = "http://dc.oclean.com/putinstorage";
    private static final String stockGetPostFromYundingUrl = "http://dc.oclean.com/getinstorage";
    private static final String sendStockPostConfirmToYundingUrl = "http://dc.oclean.com/setconfirmstatus";

    @Autowired
    BaseDao baseDao;
    @Autowired
    EdiLogDao ediLogDao;
    @Autowired
    EdiSuccessLogDao ediSuccessLogDao;

    @Override
    public Map<String, Object> postStockToYunding(Integer id) {
        Map<String,Object> data = getMainData(id);
        List<Map<String,Object>> datas = new LinkedList<Map<String,Object>>();
        datas.add(data);

        String timestamp = String.valueOf(System.currentTimeMillis()/1000);
        String outerNo = String.valueOf(data.get("outer_no"));

        Map<String,Object> postMapData = new HashMap<>();
        postMapData.put("app_key", Constant.yundingAppKey);
        postMapData.put("time_stamp",timestamp);
        postMapData.put("data",datas);

        return postData(outerNo,postMapData,timestamp);
    }

    private Map<String,Object> postData(String outerNo,Map<String,Object> data,String timestamp){
        Map<String,Object> res = new HashMap<>();
        String jsonData = JacksonUtil.toSortJson(data);
        try{

            HttpUtil.Response response = HttpUtil.doPostToYunding(sendStockToYundingUrl,jsonData,timestamp);

            String responseText = response.getResponseText();

            logger.info("responseText:" + responseText);
            logger.info("responseCode:" + response.getStatusCode());

            if(response.getStatusCode()!=200){
                throw new RuntimeException("yunding server error:" + responseText);
            }

            Map<String,Object> responseMap = JacksonUtil.fromJson(response.getResponseText());

            if(!"0".equals(String.valueOf(responseMap.get("code")))){
                res.put("success",false);
                res.put("remark",responseMap.get("message"));
            }else{
                Map<String,Object> msgJson = (Map<String,Object>) responseMap.get("msg_json");
                List<String> successCodes = (List<String>)msgJson.get("s_no");
                if(successCodes.contains(outerNo)){
                    res.put("success",true);
                    ediLogDao.save(LogUtil.getSendSuccessLog(outerNo,jsonData,"send success"));
                }else{
                    res.put("success",false);
                    res.put("remark","云顶数据中心处理失败!");
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error("error",e);

            res.put("success",false);
            res.put("remark",e.getMessage());
        }
        return res;
    }

    @Override
    public void autoPost(){
        String timestamp = String.valueOf(System.currentTimeMillis()/1000);

        Map<String,Object> postMapData = new HashMap<>();
        postMapData.put("app_key", Constant.yundingAppKey);
        postMapData.put("time_stamp",timestamp);
        postMapData.put("start_time","1970-01-01 00:00:00");
        postMapData.put("end_time","2099-01-01 00:00:00");
        postMapData.put("status",2);
        postMapData.put("page_size",100);
        postMapData.put("page_index",0);

        String jsonData = JacksonUtil.toSortJson(postMapData);
        String responseText = null;
        try {
            HttpUtil.Response response = HttpUtil.doPostToYunding(stockGetPostFromYundingUrl,jsonData,timestamp);

            if(response.getStatusCode()!=200){
                responseText = "yunding server error";
                throw new RuntimeException(response.getResponseText());
            }

            responseText = response.getResponseText();

            logger.info("responseText" + responseText);

            Map<String,Object> responseMap = JacksonUtil.fromJson(response.getResponseText());

            if(!"0".equals(String.valueOf(responseMap.get("code")))){
                ediLogDao.save(LogUtil.getRequestFailLog(responseText));
                return;
            }

            if(responseMap.get("data")==null){
                return;
            }

            List<Map<String,Object>> datas = (List<Map<String,Object>>) responseMap.get("data");
            if(datas.size()>0){
                execPostProcedure(datas,responseText);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error("error",e);
            ediLogDao.save(LogUtil.getPostFailLog(responseText,e.getMessage()));
        }
    }

    public void execPostProcedure(List<Map<String,Object>> datas,String responseText){
        String code = null;
        String piClass = null;
        EdiSuccessLog postSuccessHist = null;
        for(Map<String,Object> data:datas){
            code = String.valueOf(data.get("outer_no"));
            piClass = String.valueOf(data.get("src_order_type"));
            postSuccessHist = null;
            try {
                postSuccessHist = ediSuccessLogDao.findByCodeAndType(code,piClass);
                if(postSuccessHist!=null){ //说明之前已经过账成功
                    postConfirmToYunding(code,1);
                }else{ //没有记录，说明没有过账成功
                    String out = baseDao.callProcedure("SP_YUNDING_STOCKPOST",new Object[]{code,piClass});
                    if (out!=null){
                        ediLogDao.save(LogUtil.getPostFailLog(code,responseText,out));
                    }else{
                        ediLogDao.save(LogUtil.getPostSuccessLog(code,responseText));
                        ediSuccessLogDao.save(LogUtil.getLogToAvoidRepeatPost(code,piClass));  //记录到edi_post_log，防止调用接口失败，下次重复过账
                        postConfirmToYunding(code,1);
                    }
                }

            }catch (Exception e){
                e.printStackTrace();
                logger.error("error",e);
                ediLogDao.save(LogUtil.getPostFailLog(code,responseText,e.getMessage()));
            }

        }
    }

    @Override
    public void postConfirmToYunding(String code,int type){
        String timestamp = String.valueOf(System.currentTimeMillis()/1000);

        Map<String,Object> postMapData = new HashMap<>();
        postMapData.put("app_key", Constant.yundingAppKey);
        postMapData.put("time_stamp",timestamp);
        postMapData.put("type",type);
        postMapData.put("outer_no",code);

        String jsonData = JacksonUtil.toSortJson(postMapData);
        try{
            HttpUtil.Response response = HttpUtil.doPostToYunding(sendStockPostConfirmToYundingUrl,jsonData,timestamp);
            logger.info("confirm response:" + response.getResponseText());
        }catch (Exception e){
            e.printStackTrace();
            logger.error("error",e);
        }
    }

    private Map<String,Object> getMainData(Integer id){
        Map<String,Object> data = new HashMap<>();
        SqlRowSet rs = baseDao.getJdbcTemplate().queryForRowSet("select pi_id,pi_class,pi_inoutno,pi_whcode,pi_purpose,pi_remark,wh_type,ve_add1,ve_contact,ve_tel,pi_transport from prodinout left join warehouse on pi_whcode=wh_code left join Vendor on pi_cardcode = ve_code where pi_id=" + id);
        String piClass = null;
        if(rs.next()){
            piClass = rs.getString("pi_class");
            data.put("outer_no",rs.getString("pi_inoutno"));
            data.put("warehouse_no",getWarehouseCode(piClass,rs.getString("pi_whcode"),rs.getString("pi_purpose")));
            data.put("out_warehouse_no",rs.getString("pi_whcode"));
            data.put("remark",rs.getString("pi_remark"));
            data.put("order_type",getOrderType(piClass));
            data.put("src_order_type",piClass);
            data.put("warehouse_type",getWhType(rs.getString("wh_type")));
            data.put("rec_type",rs.getString("pi_transport"));
            data.put("rec_address",rs.getString("ve_add1"));
            data.put("rec_contacts",rs.getString("ve_contact"));
            data.put("rec_phone",rs.getString("ve_tel"));
            data.put("details_list",getDetailData(id));
        }
        return data;
    }

    private String getWarehouseCode(String piClass,String piWhCode,String piPurpose){
        if("拨出单".equals(piClass)){
            return piPurpose;
        }
        return piWhCode;
    }

    private List<Map<String,Object>> getDetailData(Integer id){
        List<Map<String,Object>> datas = new LinkedList<>();
        Map<String,Object> data = new HashMap<>();
        SqlRowList rs = baseDao.queryForRowSet("select pd_piclass,pd_id,pd_ordercode,pd_orderdetno,pd_batchcode,pd_prodcode,pd_inqty,pd_outqty,pd_description,pd_whcode,pd_inwhcode from prodiodetail where pd_piid=" + id);
        String piClass = null;
        String whCode = null;
        String pdinWhCode = null;
        while (rs.next()){
            data = new HashMap<>();
            piClass = rs.getString("pd_piclass");
            whCode = rs.getString("pd_whcode");
            pdinWhCode = rs.getString("pd_inwhcode");
            data.put("child_no",rs.getString("pd_id"));
            data.put("purchase_no",rs.getString("pd_ordercode"));
            data.put("purchase_detno",rs.getString("pd_orderdetno"));
            data.put("batch_no",rs.getString("pd_batchcode"));
            data.put("stockin_num",getQty(piClass,rs.getInt("pd_inqty"),rs.getInt("pd_outqty")));
            data.put("spec_no",rs.getString("pd_prodcode"));
            data.put("remark",rs.getString("pd_description"));
            data.put("warehouse_no",getInWarehouseNo(piClass,whCode,pdinWhCode));
            data.put("out_warehouse_no",getOutWarehouseNo(piClass,whCode));

            datas.add(data);
        }
        return datas;
    }

    private String getInWarehouseNo(String piClass,String whcode,String pdinwhcode){
        String code = whcode;
        if("拨出单".equals(piClass)){
            code = pdinwhcode;
        }
        return code;
    }

    private String getOutWarehouseNo(String piClass,String whcode){
        String code = null;
        if("拨出单".equals(piClass)){
            code = whcode;
        }
        return code;
    }

    private int getQty(String piClass,int inQty,int outQty){
        int correctQty = 0;
        switch (piClass){
            case "采购验收单":
                correctQty = inQty;
                break;
            case "采购验退单":
                correctQty = outQty;
                break;
            case "委外验收单":
                correctQty = inQty;
                break;
            case "委外验退单":
                correctQty = outQty;
                break;
            case "拨出单":
                correctQty = outQty;
                break;
            case "其它出库单":
                correctQty = outQty;
                break;
            case "其它入库单":
                correctQty = inQty;
                break;
            case "借货出货单":
                correctQty = outQty;
                break;
            case "借货归还单":
                correctQty = inQty;
                break;
            default:break;
        }
        return correctQty;
    }

    private int getWhType(String whtype){
        int whType = -1;
        switch (whtype){
            case "良品仓":
                whType = 1;
                break;
            case "不良品仓":
                whType = 2;
                break;
            case "暂收仓":
                whType = 3;
                break;
            default:break;
        }
        return whType;
    }

    private int getOrderType(String piClass){
        int orderType = -1;
        switch (piClass){
            case "采购验收单":
                orderType = 0;
                break;
            case "委外验收单":
                orderType = 0;
                break;
            case "其它入库单":
                orderType = 0;
                break;
            case "借货归还单":
                orderType = 0;
                break;
            case "拨出单":
                orderType = 1;
                break;
            case "采购验退单":
                orderType = 2;
                break;
            case "委外验退单":
                orderType = 2;
                break;
            case "其它出库单":
                orderType = 2;
                break;
            case "借货出货单":
                orderType = 2;
                break;
            default:break;
        }
        return orderType;
    }
}
