package im.zhaojun.system.service;

import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageHelper;
import im.zhaojun.common.util.DateUtils;
import im.zhaojun.common.util.ThreadPoolUtil;
import im.zhaojun.common.util.TransHelper;
import im.zhaojun.system.mapper.SbtdspsrMapper;
import im.zhaojun.system.mapper.TraffdevicewriteresultMapper;
import im.zhaojun.system.model.*;
import lombok.extern.log4j.Log4j2;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import tk.mybatis.mapper.entity.Condition;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

@Service
@Slf4j
public class TraffdevicewriteresultService {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${qingzhi.devicewrite.url}")
    private String url;
    @Value("${qingzhi.devicewrite.timeout}")
    private Integer timeout;

    @Value("${qingzhi.devicewritesupplier.name}")
    String devicesupplier;

    @Value("${qingzhi.devicewrite.url}")
    String devicewriteurl;

    @Autowired
    SbtdspsrMapper sbtdspsrMapper;

    @Autowired
    private TraffdevicewriteresultMapper traffdevicewriteresultMapper;


    /**
     * ��ѯ��ҳ
     */
    public List<SbtdspsrResult> querySbtdspsrResultByPage(SbtdspsrParams sbtdspsr) {
        PageHelper.startPage(sbtdspsr.getPage(), sbtdspsr.getLimit());
        return traffdevicewriteresultMapper.querySbtdspsrResultByPage(sbtdspsr);
    }
    /**
     * ��ѯ��ҳ
     */
    public List<Traffdevicewriteresult> queryTraffdevicewriteresultByPage(TraffdevicewriteresultParams traffdevicewriteresult) {
        PageHelper.startPage(traffdevicewriteresult.getPage(), traffdevicewriteresult.getLimit());
        Condition condition = new Condition(Traffdevicewriteresult.class);
        Example.Criteria criteria = condition.createCriteria();
        if (traffdevicewriteresult.getCreatetime() != null) {
            criteria.andEqualTo("createtime", traffdevicewriteresult.getCreatetime());
        }
        if (traffdevicewriteresult.getPushdesc() != null) {
            criteria.andEqualTo("pushdesc", traffdevicewriteresult.getPushdesc());
        }
        if (traffdevicewriteresult.getPushstatus() != null) {
            criteria.andEqualTo("pushstatus", traffdevicewriteresult.getPushstatus());
        }
        if (StringUtils.isNotBlank(traffdevicewriteresult.getSbbh())) {
            criteria.andLike("sbbh", "%" + traffdevicewriteresult.getSbbh()+"%" );
        }
        if (traffdevicewriteresult.getTdbh() != null) {
            criteria.andEqualTo("tdbh", traffdevicewriteresult.getTdbh());
        }
        if (traffdevicewriteresult.getLikePushdesc() != null) {
            criteria.andLike("pushdesc", "%" + traffdevicewriteresult.getLikePushdesc() + "%");
        }
        if (traffdevicewriteresult.getLikePushstatus() != null) {
            criteria.andLike("pushstatus", "%" + traffdevicewriteresult.getLikePushstatus() + "%");
        }
        if (StringUtils.isNotBlank(traffdevicewriteresult.getLikeSbbh())) {
            criteria.andLike("sbbh", "%" + traffdevicewriteresult.getLikeSbbh() + "%");
        }
        if (traffdevicewriteresult.getLikeTdbh() != null) {
            criteria.andLike("tdbh", "%" + traffdevicewriteresult.getLikeTdbh() + "%");
        }
        if (StringUtils.isNotBlank(traffdevicewriteresult.getCreatetimeBegin())) {
            criteria.andGreaterThanOrEqualTo("createtime", DateUtils.parseDate(traffdevicewriteresult.getCreatetimeBegin()));
        }
        if (StringUtils.isNotBlank(traffdevicewriteresult.getCreatetimeEnd())) {
            criteria.andLessThanOrEqualTo("createtime", DateUtils.parseDate(traffdevicewriteresult.getCreatetimeEnd()));
        }
        return  traffdevicewriteresultMapper.selectByCondition(condition);
    }

    /**
     * ���
     */
    public ResultObj saveTraffdevicewriteresult(Traffdevicewriteresult traffdevicewriteresult) {
        traffdevicewriteresultMapper.insertSelective(traffdevicewriteresult);
        return ResultObj.ok();
    }

    /**
     * �������
     */
    public void saveTraffdevicewriteresultList(List<Traffdevicewriteresult> traffdevicewriteresultList) {
        traffdevicewriteresultMapper.insertList(traffdevicewriteresultList);
    }

    /**
     * ����
     */
    public void updateTraffdevicewriteresult(Traffdevicewriteresult traffdevicewriteresult) {
        traffdevicewriteresultMapper.updateByPrimaryKeySelective(traffdevicewriteresult);
    }

    /**
     * ɾ��
     */
    public void deleteTraffdevicewriteresult(Traffdevicewriteresult traffdevicewriteresult) {
        traffdevicewriteresultMapper.deleteByPrimaryKey(traffdevicewriteresult);
    }

    /**
     * ����ɾ��
     */
    public void deleteTraffdevicewriteresultList(List<Traffdevicewriteresult> traffdevicewriteresultList) {
        for (Traffdevicewriteresult traffdevicewriteresult : traffdevicewriteresultList) {
            traffdevicewriteresultMapper.deleteByPrimaryKey(traffdevicewriteresult);
        }
    }

    @Autowired
    QingZhiLoginCacheService qingZhiLoginCacheService;

    private static CompletionService<ResultObj> threadService  = new ExecutorCompletionService<ResultObj>(ThreadPoolUtil.getPool());

    public List<ResultObj> sendDevices(List<SbtdspsrParams> sbtdspsrlist) {
        log.info("senddevice begin");
        List<ResultObj> resultlist=new ArrayList<>();
        for (SbtdspsrParams val : sbtdspsrlist) {
            log.info("senddevice val"+val.getSbbh());
                    Traffdevicewriteresult param=new Traffdevicewriteresult();
                    ResultObj obj = sendToGuangda(val, param);
                    obj.setData(val.getXh());
                    log.info("ResultObj====="+obj.toString());
                    resultlist.add(obj);
        }
        return resultlist;
    }

    public ResultObj sendToGuangda(SbtdspsrParams val, Traffdevicewriteresult param) {
        if (val.getXzbh() == null) {
            log.error("deviceWritePost  {} : regist remsg...", "设备所属单位机构编码必填");
            return ResultObj.error(ResponseEnum.E_1002.getCode(), "设备所属单位机构编码必填");
        } else if (val.getDeviceconfig() == null) {
            log.error("deviceWritePost  {} : regist remsg...", "请impn先配置设备推送配置");
            return ResultObj.error(ResponseEnum.E_1002.getCode(), "请impn先配置设备推送配置");
        } else {
            //转成第三方对象
            log.info("senddevice transer");
            DeviceWriteParam item = JSONUtil.toBean(val.getDeviceconfig(), DeviceWriteParam.class);
            item.setDeviceID(val.getWbbh());
            item.setDeviceName(val.getTdmc());
            item.setRegionID(val.getXzbh());
            item.setDeviceStatus(1);
            item.setDeviceSupplier(devicesupplier);
            item.setDataType(1);
            WriteResultObj writeResultObj=null;
            try {
                //调用第三方的restful
                log.error("调用第三方的restful" + item.toString());
                writeResultObj = deviceWritePost(item);
            }
            catch (TimeoutException e) {
                log.error("eventwrite - sendEvents 请求超时:" + e.toString());
                return ResultObj.error(ResponseEnum.E_1008.getCode(), ResponseEnum.E_1008.getMsg());
            } catch (Exception e) {
                log.error("eventwrite - sendEvents 异常:" + e.toString());
                //return ResultObj.error(ResponseEnum.E_9999.getCode(), e.toString());
            }
            if (writeResultObj == null) {
                return ResultObj.error(ResponseEnum.E_9999.getCode(), "token凭证获取失败");
            }
            log.info("eventwrite - sendEvents success update database  " );
            param.setSbbh(val.getSbbh());
            param.setTdbh(val.getTdbh());
            Traffdevicewriteresult traffdevicewriteresult = traffdevicewriteresultMapper.selectOne(param);

            param.setPushdesc(writeResultObj.getMessage());
            param.setXzbh(val.getXzbh());
            param.setPushcount(1L);
            if (writeResultObj.getStatus() == 200) {
                param.setPushstatus(Long.valueOf(0));
            } else {
                param.setPushstatus(Long.valueOf(1));
            }
            //数据库记录操作
            if (traffdevicewriteresult == null) {
                traffdevicewriteresultMapper.insertSelective(param);
            } else {
                if (null!=traffdevicewriteresult.getPushstatus()&& traffdevicewriteresult.getPushstatus() == 0) {
                    param.setPushstatus(Long.valueOf(0));
                    param.setPushcount(traffdevicewriteresult.getPushcount() + 1);
                }
                traffdevicewriteresultMapper.updateByPrimaryKeySelective(param);
            }
            if (writeResultObj.getStatus() == 200) {
                param.setPushstatus(Long.valueOf(0));
                return ResultObj.ok(writeResultObj.getStatus());
            } else {
                param.setPushstatus(Long.valueOf(1));
                return ResultObj.error(writeResultObj.getStatus(), writeResultObj.getMessage());
            }
        }
    }

    public ResultObj updateAndRegist(SbtdspsrParam sbtdspsr) {
        ResultObj res;
        String pushdesc;
        long pushstatus = 0;
        assert sbtdspsr != null;
        if (sbtdspsr.getXzbh() == null) {
            res = ResultObj.error(ResponseEnum.E_1002.getCode(), "设备所属单位机构编码必填");
            log.error("deviceWritePost  {} : regist remsg...", "设备所属单位机构编码必填");
        } else if (sbtdspsr.getDeviceconfig() == null) {
            res = ResultObj.error(ResponseEnum.E_1002.getCode(), "请impn先配置设备推送配置");
            log.error("deviceWritePost  {} : regist remsg...", "请impn先配置设备推送配置");
        } else {
            res = doDeviceWriteGetResultObj(sbtdspsr);
        }
        if (res.getStatus() == 200) {
            pushdesc = res.getData().toString();
        } else {
            pushdesc = res.getMsg();
            pushstatus = 1;
        }
        //数据库记录操作
        Traffdevicewriteresult traffdevicewriteresult = traffdevicewriteresultMapper.selectOne(TransHelper.transDeviceWriteResult(sbtdspsr));
        if (traffdevicewriteresult == null) {
            traffdevicewriteresultMapper.insertSelective(TransHelper.transDeviceWriteResult(sbtdspsr, pushstatus, pushdesc));
        } else {
            if (traffdevicewriteresult.getPushstatus() == 0) {
                pushstatus = 0;
            }
            traffdevicewriteresultMapper.updateByPrimaryKeySelective(TransHelper.transDeviceWriteResult(sbtdspsr, pushstatus, pushdesc, traffdevicewriteresult.getPushcount() + 1));
        }
        return res;
    }

    public ResultObj registall(HttpServletResponse response) {
        response.setContentType("text/html;charset=utf-8");
        String ret;
        int count, susscee = 0, fail = 0;
        List<SbtdspsrParam> list = sbtdspsrMapper.selectDeviceWrite();
        count = list.size();
        try {
            write(response, "共查询出需要写入的设备" + count + "条");
        } catch (IOException e) {
            log.error("设备批量写入 registall -->>io异常" + e.toString());
        }
        for (SbtdspsrParam val : list) {
            try {
                write(response, "--->>>开始写入第" + (susscee + fail + 1) + "条,剩余" + (count - susscee - fail - 1) + "条。设备编号:" + val.getSbbh() + ",通道编号:" + val.getTdbh() + ",设备名称:" + val.getTdmc());
                ResultObj regest = updateAndRegist(val);
                if (regest.getStatus() == 200) {
                    susscee++;
                    write(response, "<<<---写入成功:" + regest.getData());
                } else {
                    fail++;
                    write(response, "<<<---写入失败:" + regest.getMsg());
                }
            } catch (IOException e) {
                log.error("设备批量写入 registall -->>io异常" + e.toString());
            }
        }
        ret = "查询出需要设备写入的设备数:" + count + "条,其中成功" + susscee + "条，失败" + fail + "条";
        try {
            write(response, ret);
        } catch (IOException e) {
            log.error("设备批量写入 registall -->>io异常" + e.toString());
        }
        return ResultObj.ok(ret);
    }

    public ResultObj update(SbtdspsrParam sbtdspsr) {
        DeviceWriteParam param = TransHelper.transDevice(sbtdspsr, CodeConst.device_update);
        WriteResultObj writeResultObj = new WriteResultObj(); //deviceWritePost(param);
        if (writeResultObj.getStatus() == 200) {
            return ResultObj.ok(writeResultObj.getMessage());
        }
        return ResultObj.error(writeResultObj.getStatus(), writeResultObj.getMessage());
    }

    public ResultObj remove(SbtdspsrParam sbtdspsr) {
        DeviceWriteParam param = TransHelper.transDevice(sbtdspsr, CodeConst.device_remove);
        WriteResultObj writeResultObj = new WriteResultObj(); //deviceWritePost(param);
        if (writeResultObj.getStatus() == 200) {
            return ResultObj.ok(writeResultObj.getMessage());
        }
        return ResultObj.error(writeResultObj.getStatus(), writeResultObj.getMessage());
    }

    public ResultObj report(SbtdspsrParam sbtdspsr) {
        DeviceWriteParam param = TransHelper.transDevice(sbtdspsr, CodeConst.device_report);
        WriteResultObj writeResultObj = new WriteResultObj(); //deviceWritePost(param);
        if (writeResultObj.getStatus() == 200) {
            return ResultObj.ok(writeResultObj.getMessage());
        }
        return ResultObj.error(writeResultObj.getStatus(), writeResultObj.getMessage());
    }

    private WriteResultObj deviceWritePost(DeviceWriteParam param) throws  TimeoutException, InterruptedException,Exception{
        log.info("senddevice====="+param.toString());

        HttpHeaders headers = new HttpHeaders();
//        String token = stringRedisTemplate.opsForValue().get(qztoken);
//        if (token == null) {
        //登录
//        log.info("login", qztoken);
        String  token= qingZhiLoginCacheService.keepAlive();
        log.error("deviceWritePost  {} : redis token empty..", token);
//            return null;
//        }
        log.info("qztoken send  guangda  token", token);
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        headers.add("token", token);//
        List<DeviceWriteParam> list = new ArrayList<>();
        list.add(param);
        HttpEntity<List<DeviceWriteParam>> requestEntity = new HttpEntity<>(list, headers);
        WriteResultObj writeResultObj = CompletableFuture.supplyAsync(() -> restTemplate.postForObject(devicewriteurl, requestEntity, WriteResultObj.class)).get(timeout, TimeUnit.SECONDS);
        log.info("qztoken send  guangda result", writeResultObj.toString());

        return writeResultObj;
    }

    private ResultObj doDeviceWriteGetResultObj(SbtdspsrParam sbtdspsr) {
        ResultObj res;
        sbtdspsr.setSbcsName(devicesupplier);
        //组装请求数据
        DeviceWriteParam param = TransHelper.transDevice(sbtdspsr, CodeConst.device_regist);
        WriteResultObj writeResultObj;
        try {
            //发送请求返回结果
            writeResultObj = deviceWritePost(param);
            if (writeResultObj == null) {
                writeResultObj = new WriteResultObj(ResponseEnum.E_9999.getCode(), "token凭证获取失败");
            }
        } catch (TimeoutException e) {
            log.error("devicewrite - sendEvent 请求超时:" + e.toString());
            writeResultObj = new WriteResultObj(ResponseEnum.E_1008.getCode(), ResponseEnum.E_1008.getMsg());
        } catch (Exception e) {
            log.error("devicewrite - sendEvent 异常:" + e.toString());
            writeResultObj = new WriteResultObj(ResponseEnum.E_9999.getCode(), e.toString());
        }
        //判断成功还是失败
        if (writeResultObj.getStatus() == 200) {
            res = ResultObj.ok(writeResultObj.getMessage());
//            log.info("deviceWritePost  {} : regist remsg...Data=" + param.toString(), writeResultObj.toString());
        } else {
            res = ResultObj.error(writeResultObj.getStatus(), writeResultObj.getMessage());
            log.error("deviceWritePost  {} : regist remsg...Data=" + param.toString(), writeResultObj.toString());
        }
        return res;
    }

    private void write(HttpServletResponse response, String content) throws IOException {
        response.getWriter().write(content + "<br/>");
        response.flushBuffer();
        response.getWriter().flush();
    }

    public ResultObj updateAndRegists(List<SbtdspsrParam> sbtdspsrs) {
        int error = 0;
        int success = 0;
        for (SbtdspsrParam ta : sbtdspsrs) {
            ResultObj resultObj = updateAndRegist(ta);
            boolean successFlag = resultObj.getStatus() == ResponseEnum.SUCCESS.getCode();
            /* 成功 */
            if (successFlag) {
                success++;
                continue;
            }
            error++;
        }
        return ResultObj.error(ResponseEnum.SUCCESS.getCode(), "成功" + success + "条|失败" + error + "条");
    }

}