package com.uas.eis.serviceImpl;

import com.alibaba.fastjson.JSON;
import com.uas.eis.core.support.TokenHandler;
import com.uas.eis.dao.BaseDao;
import com.uas.eis.dao.SqlMap;
import com.uas.eis.dao.SqlRowList;
import com.uas.eis.entity.ErrorMessage;
import com.uas.eis.entity.ErrorMsg;
import com.uas.eis.entity.StepWork.StationReq;
import com.uas.eis.entity.StepWork.TestReq;
import com.uas.eis.exception.ApiStepWorkException;
import com.uas.eis.exception.SystemException;
import com.uas.eis.sdk.entity.ApiResult;
import com.uas.eis.sdk.entity.StepWorkApiResult;
import com.uas.eis.sdk.resp.StepWorkApiResponse;
import com.uas.eis.service.StepWorkService;
import com.uas.eis.utils.*;
import org.aspectj.weaver.ast.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Service
public class StepWorkServiceImpl implements StepWorkService {
    @Autowired
    private BaseDao baseDao;

    @Override
    public String login(String username, String password) {
        SqlRowList rs = baseDao.queryForRowSet("select AE_SECRET from APIEMPLOYEE where AE_KEY=?",username);
        if(rs.next()){
            System.out.println("secret:"+MD5Util.encrypt32Up(rs.getString("ae_secret")));
          if(!password.equals(MD5Util.encrypt32Up(rs.getString("ae_secret")))){
              throw new ApiStepWorkException(new StepWorkApiResult(ErrorMessage.ACCESSSECRET_ERROR));
          }else{
              return TokenHandler.createToken(username,rs.getString("ae_secret"));
          }
        }else{
            throw new ApiStepWorkException(new StepWorkApiResult(ErrorMessage.ACCESSKEY_ERROR));
        }
    }

    /**
     * 保存测试信息并且过站
     * @param data
     * @return
     *  {
     *  "workOrderNo":"WO20220826000002SHD", //工单号 必填
     *  "stationCode":"GW--001",  //工位编码 必填
     * "routeCode":"22b443b4fa379a546330f4e984cc6ed1", //工序编号 必填
     * "sequenceNumber":"[P]2022083426046[B]",//产品SN 必填
     * "eventResult":"PASS", 测试结果：PASS(合格)，FAIL（不合格） 必填
     *  failureCode MES不良配置里维护的信息 * 注：PASS可以不用传， 如果是FAIL不良代码就必传 非必填
     *	extendSequenceNumber 测试合格后会把三方条码和组合体SN组合，后续扫描其中任意条码都可以识别。多个条码中间用逗分隔 非必填
     * 	machineTestData	设备测试数据 非必填 Json可以传产品多次测试记录。results的键值需要和titles的键值对应Titles中的键值不能重复
     * 	isInputSn	 是否属于投入产品 非必填 Boolean (true:根据投入SN过站并生成产品数据，false[默认]:从工单中查找是否有过站SN)
     * }
     *
     */
    @Override
    public StepWorkApiResult<Map<String,Object>> test(HttpServletRequest request ,String data) {
        insertLogger(data,"test");
        return testmain(request,data);
    }

    /**
     *  * {
     *      *  "workOrderNo":"WO20220826000002SHD",  //工单号
     *      * "stationCode":"GW--001",  //工位编码
     *      * "routeCode":"22b443b4fa379a546330f4e984cc6ed1", //工序编号
     *      * "sequenceNumber":"[P]2022083426046[B]" //产品SN
     *      * }
     * @param data
     * @return
     */
    @Override
    public StepWorkApiResult<Map<String,Object>> station(HttpServletRequest request , String data) {
        insertLogger(data,"station");
        return stationmain(request,data);
    }

    /**
     * 工单绑定，工序检测
     *
     */
    private Map<String,Object> checkStep(String macode,String sourcecode,String sncode,String usercode ){
        List<String> list = new ArrayList<String>();
        /**
         *     v_i_macode  in varchar2 ,
         *     v_i_sourcecode in varchar2,
         *     v_i_sncode in varchar2,
         *     v_i_usercode in varchar2,
         *     v_o_macode out varchar2,
         *     v_o_msid out int,
         *     v_o_errmsg out varchar2
         */
        list = baseDao.callProcedureWithOut("CS_CHECKSTEPSNANDMACODE", new Object[]{
                macode, sourcecode,sncode,usercode
        }, new Integer[]{1, 2, 3, 4}, new Integer[]{5, 6, 7});
        Map<String,Object> map = new HashMap<>();
        String msg = list.get(2);
        if(StringUtil.hasText(msg)){
            map.put("success",false);
            map.put("msg",msg);
        }else{
            map.put("success",true);
            map.put("macode",list.get(0));
        }
        return map;

    }

    private boolean stepPassed(String iMakeCode, String iSourceCode, String iSN, String iUserCode, String iResult) {
        String msg = baseDao.callProcedure("CS_SETSTEPRESULT",
                iMakeCode,
                iSourceCode,
                iSN,
                iUserCode,
                iResult);
        if(StringUtil.hasText(msg)){
            throw new ApiStepWorkException(new StepWorkApiResult(false,400,msg));
        }else{
            return true;
        }
    }

    /**
     * 保存测试数据并且过站
     * @param macode
     * @param sccode
     * @param sncode
     * @param isok
     * @param failureCode
     * @param machineTestData
     * "machineTestData":{
     * "machineCode":"JT001",
     * "titles":{
     * "芯片型号":"100",
     * "开机电流":"200",
     *"线损补偿":"300",
     * "输出功率":"400",
     * "测试时长":"500",
     * "测试结果":"600"},
     * "results":[{
     * "芯片型号":"XXC5121",
     * "开机电流":"9.438",
     * "线损补偿":"11.00",
     * "输出功率":"11.683",
     * "测试时长":"31.37",
     * "测试结果":"成功"
     * }]}
     */
    private void saveTestDataAndPassed(String macode, String stepcode,String sccode, String sncode, String isok, String failureCode,
                                       Object isinput,Object machineTestData,Object extendSequenceNumber,String usercode) {
        //保存测试数据
        Object machinecode = "";
        List<Map<Object,Object>> sqldata = new ArrayList<>();
        int mainid = baseDao.getSeqId("STEPTESTMAIN_SEQ");
        if(StringUtil.hasText(machineTestData)){
            Map<Object, Object> map = null;
            if (machineTestData instanceof Map) {
                map = (Map<Object, Object>) machineTestData;
            }else{
                map = BaseUtil.parseFormStoreToMap(machineTestData.toString());
            }
            if(!map.isEmpty()) {
                int detno=1;
                machinecode = map.containsKey("machineCode")?map.get("machineCode"):"";
                Object titles = map.get("titles");
                Object results = map.get("results");
                if(StringUtil.hasText(titles) && StringUtil.hasText(results)){
                   // SD_SN,SD_MAKECODE,SD_MACHINECODE,SD_INDATE,
                    Map<Object,Object> baseData = new HashMap<>() ;
                    baseData.put("SD_SN",sncode);
                    baseData.put("SD_MAKECODE",macode);
                    baseData.put("SD_MACHINECODE",machinecode);
                    baseData.put("SD_INDATE",DateUtil.parseDateToString(new Date(), Constant.YMD_HMS));
                    Map<String,Object> titledata = null;
                    if (machineTestData instanceof Map) {
                        titledata = (Map<String, Object>) titles;
                    }else{
                        titledata = FlexJsonUtil.fromJson(titles.toString());
                    }
                    List<Map<String,Object>> resultdata = null;
                    if (results instanceof List) {
                        resultdata = (List<Map<String,Object>>) results;
                    }else{
                        resultdata = FlexJsonUtil.fromJsonArray(results.toString(),HashMap.class);
                    }
                    for(Map<String,Object> m : resultdata){
                        Iterator<Map.Entry<String, Object>> iterator = titledata.entrySet().iterator();
                        baseData.put("SD_DETNO", detno);
                        detno++;
                        while (iterator.hasNext()) {
                            Map.Entry<String, Object> entry = iterator.next();
                            String key = entry.getKey();
                            Object value = entry.getValue();
                            Map<Object,Object> sqlm = new HashMap<>();
                            sqlm.putAll(baseData);
                            sqlm.put("SD_CLASS", key);
                            sqlm.put("SD_LENGTH", value);
                            sqlm.put("SD_SMID",mainid);
                            Object v = m.get(key);
                            sqlm.put("SD_ACTVALUE",v);
                            sqlm.put("SD_ID",null);
                            sqldata.add(sqlm);
                        }
                    }
                }
            }
        }
        //测试项和测试结果不一致
        /**
         * insert into STEPTESTMAIN(SM_ID,SM_SN,SM_MAKECODE,SM_STEPCODE,SM_SCCODE,SM_RESULT,SM_BADCODE,SM_ISINPUT,SM_INDATE)
         * insert into STEPTESTDETAIL(SD_ID,SD_SMID,SD_SN,SD_MAKECODE,SD_MACHINECODE,SD_INDATE,SD_CLASS,SD_StandardVALUE,SD_ACTVALUE)
         */
        //插入数据
        baseDao.execute("insert into STEPTESTMAIN(SM_ID,SM_SN,SM_TSN,SM_MAKECODE,SM_STEPCODE,SM_SCCODE,SM_RESULT,SM_BADCODE,SM_ISINPUT,SM_INDATE，sm_machineCode)" +
                "select ?,?,?,?,?,?,?,?,?,sysdate,? from dual ",mainid,sncode,extendSequenceNumber,macode,stepcode,sccode,isok,failureCode,isinput,machinecode);
        if(sqldata.size()>0){
            baseDao.execute(SqlUtil.getInsertSqlbyList(sqldata,"STEPTESTDETAIL","SD_ID"));
        }

        Object msstepcode = baseDao.getFieldDataByCondition("Makeserial", "ms_stepcode", "ms_sncode='" + sncode + "' and ms_makecode='" + macode + "'");
        Object BgCode = baseDao.getFieldDataByCondition("step", "nvl(st_badgroupcode,' ')", "st_code='" + stepcode + "'");
        Map<Object, Object> rmap = new HashMap<>();
        if("FAIL".equals(isok)){
            //将历史的不良记录更新状态
            baseDao.execute("update makebad set mb_status=-1 where mb_sncode=? and mb_makecode=? and mb_stepcode=? and mb_status=0",sncode,macode);
            baseDao.execute("insert into makebad(mb_id,mb_makecode,mb_mscode,mb_sncode,mb_inman,mb_indate,mb_stepcode,mb_sourcecode,mb_badcode,mb_badtable,mb_bgcode,mb_soncode,mb_status)" +
                    " select makebad_seq.nextval,ma_code,ms_code,ms_sncode,'EIS对接',sysdate,?,?,?,'',?,sp_soncode,0 from make left join makeserial on ms_makecode=ma_code left join " +
                    " stepproduct on sp_mothercode=ma_prodcode and sp_stepcode=ms_nextstepcode where ms_sncode=? and ms_makecode=?",stepcode,sccode,failureCode,BgCode,sncode,macode);
            //将不良的序列号的状态码设为3
            //baseDao.execute("update "+Master+".makeserial set ms_status='3' where ms_sncode='" + iSN + "' and ms_makecode='" + iMakeCode + "'");
        }else if("PASS".equals(isok) && StringUtil.hasText(failureCode)){ //强制良品也有不良代码的
            baseDao.execute("insert into makebad(mb_id,mb_makecode,mb_mscode,mb_sncode,mb_inman,mb_indate,mb_stepcode,mb_sourcecode,mb_badcode,mb_badtable,mb_bgcode,mb_soncode,mb_status)" +
                    " select makebad_seq.nextval,ma_code,ms_code,ms_sncode,'EIS对接',sysdate,?,?,?,'',?,sp_soncode,-1 from make left join makeserial on ms_makecode=ma_code left join " +
                    " stepproduct on  sp_mothercode=ma_prodcode and sp_stepcode=ms_nextstepcode where ms_sncode=? and ms_makecode=?",stepcode,sccode,failureCode,BgCode,sncode,macode);
        }
        //不良采集为良品是更新
        if (msstepcode!=null && msstepcode.toString().equals(stepcode) && isok == "PASS") {
            Object[] ob = baseDao.getFieldsDataByCondition("makeserial", "ms_status,ms_craftcode,ms_prodcode", "ms_sncode='" + sncode + "' and ms_makecode='" + macode + "'");
            if (ob!=null){
                String ms_status =ob[0].toString();
                String ms_craftcode= ob[1].toString();
                String ms_prodcode = ob[2].toString();
                if (ms_status == "3") {
                    String nextstepcode =baseDao.getFieldDataByCondition("craft left join  craftdetail on cr_id=cd_crid ", "cd_nextstepcode", "cr_code='" + ms_craftcode + "' and cr_prodcode='" + ms_prodcode + "' and cd_stepcode='" + stepcode + "'").toString();
                    baseDao.updateByCondition("makeserial", "ms_status=1,ms_nextstepcode='" + nextstepcode + "'", "ms_sncode='" + sncode + "' and ms_makecode='" + macode + "'");
                    baseDao.updateByCondition("makebad", "mb_status=-1", "mb_sncode='" + sncode + "' and mb_makecode='" + macode + "'");
                }
            }
        }
        //转号：CS_SNCHANGEANDBURN
        if(StringUtil.hasText(extendSequenceNumber)){
            snChange(macode,sccode,sncode,extendSequenceNumber.toString(),usercode);
        }else {
            stepPassed(macode, sccode, sncode, usercode, "PASS".equals(isok) ? "OK" : "NG");
        }
    }

    //记录日志
    private void insertLogger(String data,String type){
        baseDao.execute("insert into EISDATA(ed_id,ed_data,ed_indate,ED_TYPE)" +
                "values(EISDATA_seq.nextval,?,sysdate,?)", data,type);
    }

    @Transactional
    public StepWorkApiResult<Map<String,Object>> testmain(HttpServletRequest request,String data){
        Map<Object,Object> map =  BaseUtil.parseFormStoreToMap(data);
        String macode = " ";
        if(StringUtil.hasText(map.get("workOrderNo"))){//工单号可填写可不填
            macode = map.get("workOrderNo").toString();
        }
        Object sccode = map.get("stationCode");
        if(!StringUtil.hasText(sccode)){
            return StepWorkApiResponse.failRsp(400,"工位编码（stationCode）不能为空！");
        }
        Object stepcode = map.get("routeCode");
        if(!StringUtil.hasText(stepcode)){
            return StepWorkApiResponse.failRsp(400,"工序编号（routeCode）不能为空！");
        }
        Object sncode = map.get("sequenceNumber");
        if(!StringUtil.hasText(sncode)){
            return StepWorkApiResponse.failRsp(400,"产品SN（sequenceNumber）不能为空！");
        }
        //测试结果
        Object isok = map.get("eventResult");  //测试结果：PASS(合格)，FAIL（不合格） 必填 ，测试强制合格有的时候也会有不良代码
        Object failureCode =map.get("failureCode");
        if(!StringUtil.hasText(isok)){
            return StepWorkApiResponse.failRsp(400,"测试结果（eventResult）不能为空！");
        }else{
            if(!"PASS".equals(isok) && !"FAIL".equals(isok)){
                return StepWorkApiResponse.failRsp(400,"测试结果值【"+isok+"】,只能是PASS或者FAIL！");
            }
            if("FAIL".equals(isok) && !StringUtil.hasText(failureCode)){
                return StepWorkApiResponse.failRsp(400,"测试结果为不合格,不良代码（failureCode）值必填！");
            }
        }
        if(StringUtil.hasText("failureCode")) {
            String bccode = baseDao.getJdbcTemplate().queryForObject("select max(bc_code) from badcode where bc_code=?", String.class, failureCode);//oErrMessage = "不良代码"+BadCode[i]+"不存在";
            if (null == bccode) {
                throw new ApiStepWorkException(new StepWorkApiResult(false, 400, "测试不良代码：" + failureCode + "在MES系统不存在!"));
            }
        }
        String usercode = String.valueOf(request.getSession().getAttribute("usercode"));
        //工序校验
        Map<String,Object> remap =  checkStep(macode,sccode.toString(),sncode.toString(),usercode);
        if(Boolean.valueOf(remap.get("success").toString())){
            //工序保存测试数据并且过站
            saveTestDataAndPassed(remap.get("macode").toString(),stepcode.toString(),sccode.toString(),sncode.toString(),
                    isok.toString(),failureCode.toString(),map.get("isinput"),map.get("machineTestData"),
                    map.get("extendSequenceNumber"),usercode);
            return StepWorkApiResponse.successRsp(200,"【"+sncode+"】产品序列号过站成功!");
        }else{
            return StepWorkApiResponse.failRsp(400,remap.get("msg").toString());
        }
    }

    @Transactional
    public StepWorkApiResult<Map<String,Object>> stationmain(HttpServletRequest request ,String data) {
        Map<Object, Object> map = BaseUtil.parseFormStoreToMap(data);
        String macode = " ";
        if (StringUtil.hasText(map.get("workOrderNo"))) {//工单号可填写可不填
            macode = map.get("workOrderNo").toString();
        }
        Object sccode = map.get("stationCode");
        if (!StringUtil.hasText(sccode)) {
            return StepWorkApiResponse.failRsp(400, "工位编码（stationCode）不能为空！");
        }
        Object stepcode = map.get("routeCode");
        if (!StringUtil.hasText(stepcode)) {
            return StepWorkApiResponse.failRsp(400, "工序编号（routeCode）不能为空！");
        }
        Object sncode = map.get("sequenceNumber");
        if (!StringUtil.hasText(sncode)) {
            return StepWorkApiResponse.failRsp(400, "产品SN（sequenceNumber）不能为空！");
        }
        String usercode = String.valueOf(request.getSession().getAttribute("usercode"));
        Map<String, Object> remap = checkStep(macode, sccode.toString(), sncode.toString(), usercode);
        if (Boolean.valueOf(remap.get("success").toString())) {
            stepPassed(remap.get("macode").toString(), sccode.toString(), sncode.toString(), usercode, "OK");
            return StepWorkApiResponse.successRsp(200, "【" + sncode + "】产品序列号过站成功!");
        } else {
            return StepWorkApiResponse.failRsp(400, remap.get("msg").toString());
        }
    }

    private boolean snChange(String iMakeCode, String iSourceCode, String tsn,String iSN, String iUserCode) {
        //v_i_ifrechange in number default 0,-- 标识是否重复转号 0否,1是
        String msg = baseDao.callProcedure("CS_SNCHANGEANDBURN",
                tsn,iSN,iSourceCode,iUserCode,iMakeCode,0,
                  null,null,null,null,null,
                  iSN,null,null,null,null,null,null,null,null
              );
        if(StringUtil.hasText(msg)){
            throw new ApiStepWorkException(new StepWorkApiResult(false,400,msg));
        }else{
            return true;
        }
    }

      /* SqlRowList rs=baseDao.queryForRowSet("select nvl(st_ifinput,0)st_ifinput,nvl(st_ifoqc,0)st_ifoqc,nvl(st_ifweigh,0)st_ifweigh from "+Master+".source left join "+Master+".step on sc_stepcode=st_code where sc_code='"+iResCode+"'");
        if(rs.next()){
            String st_ifinput=rs.getString("st_ifinput");
            String st_ifoqc=rs.getString("st_ifinput");
            String st_ifweigh=rs.getString("st_ifweigh");
            if(st_ifinput.equals("-1")){
                oErrMessage = "上料工序必须在客户端进行过站";
                rmap.put("oErrMessage",oErrMessage);
                return rmap;
            }
            if(st_ifoqc.equals("-1")){
                oErrMessage = "OQC必须在客户端进行过站";
                rmap.put("oErrMessage",oErrMessage);
                return rmap;
            }
            if(st_ifweigh.equals("-1")){
                oErrMessage = "称重工序必须在客户端进行过站";
                rmap.put("oErrMessage",oErrMessage);
                return rmap;
            }
        }*/

}
