package com.xy.service.factory.sim.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.xy.Enum.ctwing.BindTypeEnum;
import com.xy.annotate.Factory;
import com.xy.config.DeviceThreadPoolConfig;
import com.xy.dto.CtWingDto;
import com.xy.dto.CtWingVo;
import com.xy.dto.DeviceSimPickRecordsDto;
import com.xy.dto.SimInfoDto;
import com.xy.entity.DeviceInfo;
import com.xy.entity.SysDictRedis;
import com.xy.service.DeviceInfoServiceImpl;
import com.xy.service.DeviceSimPickRecordsServiceImpl;
import com.xy.service.factory.sim.SimInfoFactory;
import com.xy.utils.*;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 电信
 * </p>
 *
 * @author hechunping
 * @since 2024/8/20
 */
@Slf4j
@Factory(type = "电信")
@AllArgsConstructor
public class CtWingFactoryImpl implements SimInfoFactory {
    private final DeviceSimPickRecordsServiceImpl simPickRecordsService;

    private final DeviceInfoServiceImpl deviceInfoService;

    /**
     * 三码查询
     *
     * @param iccid
     * @return
     */
    @SneakyThrows
    private CtWingVo.TelephonePlusVo telephonePlus(String iccid) {
        CtWingDto.TelephonePlusDto telephonePlusDto = new CtWingDto.TelephonePlusDto();
        telephonePlusDto.setIccid(iccid);
        CtWingVo.TelephonePlusVo vo = CtWingUtils.getTelephonePlus(telephonePlusDto);
        return vo;
    }


    @Override
    @SneakyThrows
    public R<SimInfoDto.InfoVo> info(SimInfoDto.BaseDto dto) {
        //三码查询
        CtWingVo.TelephonePlusVo telephonePlusVo = telephonePlus(dto.getIccid());
        if (!"0".equals(telephonePlusVo.getResultCode())) {
            return R.fail("三码查询错误！");
        }
        SimInfoDto.InfoVo vo = new SimInfoDto.InfoVo();
        vo.setIccid(telephonePlusVo.getIccid())
                .setImsi(telephonePlusVo.getImsi())
                .setAccessNumber(telephonePlusVo.getAccessNumber());
        //卡主状态查询
        FunctionUtils.NoParamsNoResult queryCardMainStatus = () -> {
            CtWingDto.CardMainStatusDto cardMainStatusDto = new CtWingDto.CardMainStatusDto();
            cardMainStatusDto.setAccessNumber(telephonePlusVo.getAccessNumber());
            CtWingVo.CardMainStatusVo cardMainStatusVo = CtWingUtils.queryCardMainStatus(cardMainStatusDto);
            vo.setCreateDate(cardMainStatusVo.getServCreateDate())
                    .setActiveDate(cardMainStatusVo.getServActiveDate())
                    .setNetBlockStatus(cardMainStatusVo.getNetBlockStatusName())
                    .setSimStatus(cardMainStatusVo.getOperatorDefinitionStatusName());
        };
        //在线状态
        FunctionUtils.NoParamsNoResult qryOnlineStatus = () -> {
            CtWingDto.AccessNumberOrIccid accessNumberOrIccid = new CtWingDto.AccessNumberOrIccid().setIccid(telephonePlusVo.getIccid());
            CtWingVo.OnlineStatusVo onlineStatusVo = CtWingUtils.qryOnlineStatus(accessNumberOrIccid);
            vo.setImei(onlineStatusVo.getImei())
                    .setProvince(onlineStatusVo.getProvince())
                    .setOnlineStatus(onlineStatusVo.getOnlineStatusDesc())
                    .setOnlineStartTime(onlineStatusVo.getStartTime())
                    .setOnlineEndTime(onlineStatusVo.getEndTime())
            ;
        };
        //当月流量使用总量
        FunctionUtils.NoParamsNoResult queryTraffic = () -> {
            CtWingDto.AccessNumberOrIccid accessNumberOrIccid = new CtWingDto.AccessNumberOrIccid().setIccid(telephonePlusVo.getIccid());
            CtWingVo.TrafficVo trafficVo = CtWingUtils.queryTraffic(accessNumberOrIccid);
            vo.setCurrMonthUseFlow(trafficVo.getTotalBytesCnt());
        };
        ThreadPoolUtils.excPoll(DeviceThreadPoolConfig.DEVICE_COMMON_POLL, 3)
                .execute(() -> {
                    queryCardMainStatus.run();
                })
                .execute(() -> {
                    qryOnlineStatus.run();
                })
                .execute(() -> {
                    queryTraffic.run();
                }).end();
        return R.ok(vo);
    }

    @Override
    @SneakyThrows
    public R<String> refreshNet(SimInfoDto.RefreshNetDto dto) {
        //三码查询
        CtWingVo.TelephonePlusVo telephonePlusVo = telephonePlus(dto.getIccid());
        if (!"0".equals(telephonePlusVo.getResultCode())) {
            return R.fail("三码查询错误！");
        }
        String action = dto.getAction() ? "ADD" : "DEL";
        CtWingDto.SingleCutNetDto singleCutNetDto = new CtWingDto.SingleCutNetDto()
                .setAccessNumber(telephonePlusVo.getAccessNumber())
                .setAction(action);
        CtWingVo.BaseVo baseVo = CtWingUtils.singleCutNet(singleCutNetDto);
        log.info("刷新网络，参数 {}，操作人:{}",JSONUtil.toJsonStr(singleCutNetDto),AuthorizeUtils.getLoginId(Long.class));
        if ("0".equals(baseVo.getResultCode())) {
            log.info("刷新网络成功 {}",dto.getIccid());
            return R.ok("处理成功！");
        } else {
            log.info("刷新网络失败 {}，错误描述 {}",dto.getIccid(),baseVo.getResultMsg());
            return R.fail(baseVo.getResultMsg());
        }
    }

    @Override
    @SneakyThrows
    public R<String> bindAgain(SimInfoDto.BindAgainDto dto) {
        CtWingDto.ImeiReRecordDto imeiReRecordDto = new CtWingDto.ImeiReRecordDto();
        imeiReRecordDto.setBindType(BindTypeEnum.T_1.getCode()).setImei(dto.getImei()).setIccid(dto.getIccid());
        CtWingVo.BaseVo baseVo = CtWingUtils.imeiReRecord(imeiReRecordDto);
        log.info("机卡绑定，参数 {}，操作人:{}",JSONUtil.toJsonStr(imeiReRecordDto),AuthorizeUtils.getLoginId(Long.class));
        if ("0".equals(baseVo.getResultCode())) {
            log.info("机卡绑定成功 {}",dto.getIccid());
            return R.ok("处理成功！");
        } else {
            log.info("机卡绑定失败 {}，错误描述 {}",dto.getIccid(),baseVo.getResultMsg());
            return R.fail(baseVo.getResultMsg());
        }
    }

    @Override
    @SneakyThrows
    public R<String> buyPack(SimInfoDto.BuyPackDto dto) {
        //查询设备
        DeviceInfo deviceInfo = deviceInfoService.getById(dto.getDeviceId());
        //查询字典
        SysDictRedis sysDictRedis = SysDictUtils.get("sim-packs-ctwing", dto.getPackCode());
        JSONObject jsonObject = JSONUtil.parseObj(sysDictRedis.getValue());
        String name = jsonObject.getStr("name");
        String icp = jsonObject.getStr("icp");
        Integer money = jsonObject.getInt("money");

        CtWingDto.OrderRFPFlowDto orderRFPFlowDto = new CtWingDto.OrderRFPFlowDto();
        orderRFPFlowDto.setFlowValue(dto.getPackCode()).setIccid(dto.getIccid());
        CtWingVo.BaseVo baseVo = CtWingUtils.orderRFPFlow(orderRFPFlowDto);
        if ("0".equals(baseVo.getResultCode())) {
            //保存记录
            DeviceSimPickRecordsDto.Save recordsDto = new DeviceSimPickRecordsDto.Save()
                    .setPackCode(dto.getPackCode())
                    .setIcp(dto.getIsp())
                    .setIccid(dto.getIccid())
                    .setName(name)
                    .setAmount(money)
                    .setDeviceId(dto.getDeviceId())
                    .setMercId(deviceInfo.getMercId());
            simPickRecordsService.save(recordsDto);
            return R.ok("订购成功！");
        } else {
            return R.fail(baseVo.getResultMsg());
        }
    }

    @Override
    public R<List<SimInfoDto.PackListVo>> packList() {
        Map<String, SysDictRedis> dict = SysDictUtils.get("sim-packs-ctwing");
        List<SimInfoDto.PackListVo> voList = new ArrayList<>();
        if (Emptys.check(dict)) {
            dict.forEach((k, v) -> {
                JSONObject jsonObject = JSONUtil.parseObj(v.getValue());
                String name = jsonObject.get("name").toString();
                String icp = jsonObject.get("icp").toString();
                Integer money = Integer.valueOf(jsonObject.get("money").toString());
                SimInfoDto.PackListVo vo = new SimInfoDto.PackListVo()
                        .setPackCode(v.getCode())
                        .setDesc(v.getMsg())
                        .setName(name)
                        .setIcp(icp)
                        .setMoney(money);
                voList.add(vo);
            });
        }

        return R.ok(voList);
    }


}
