package com.njzscloud.supervisory.hsoa;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.njzscloud.common.core.jackson.Jackson;
import com.njzscloud.common.http.HttpClientDecorator;
import com.njzscloud.supervisory.config.AppProperties;
import com.njzscloud.supervisory.hsoa.pojo.param.*;
import com.njzscloud.supervisory.hsoa.pojo.result.HsoaResult;
import com.njzscloud.supervisory.hsoa.pojo.result.LoginResult;
import com.njzscloud.supervisory.hsoa.pojo.result.UploadResult;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.ReentrantReadWriteLock;

@Slf4j
public class Hsoa {
    public static final HsoaApi API;
    private static final HsoaProperties hsoaProperties;
    private static final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private static final ReentrantReadWriteLock.ReadLock rlock = rwLock.readLock();
    private static final ReentrantReadWriteLock.WriteLock wlock = rwLock.writeLock();
    private static final AppProperties appProperties;
    private static String refTnt = "";
    private static String tnt = "";
    private static long lastLoginTime = 0;

    static {
        HttpClientDecorator httpClientDecorator = SpringUtil.getBean(HttpClientDecorator.class);
        appProperties = SpringUtil.getBean(AppProperties.class);
        API = httpClientDecorator.decorate(HsoaApi.class);
        hsoaProperties = SpringUtil.getBean(HsoaProperties.class);
    }

    public static HsoaResult<?> pushVehicleTrajectory(PushVehicleTrajectoryParam param) {
        login();
        try {
            rlock.lock();
            AppProperties.DefaultPlace defaultPlace = appProperties.getDefaultPlace();
            param.setCityCode(defaultPlace.getCity())
                    .setCityName(defaultPlace.getCityName())
            ;
            if (StrUtil.isBlank(tnt) || StrUtil.isBlank(refTnt)) {
                return new HsoaResult<>()
                        .setSuccess(false);
            }
            return API.pushVehicleTrajectory(param, new TokenParam().setTnt(tnt).setRefTnt(refTnt));
        } finally {
            rlock.unlock();
        }
    }

    public static HsoaResult<?> pushProvincial(PushProvincialSaveParam param) {
        login();
        try {
            rlock.lock();
            if (StrUtil.isBlank(tnt) || StrUtil.isBlank(refTnt)) {
                return new HsoaResult<>()
                        .setSuccess(false);
            }
            log.info("电子联单最终上传数据：{}", Jackson.toJsonStr(param));
            return API.pushProvincial(param, new TokenParam().setTnt(tnt).setRefTnt(refTnt));
        } finally {
            rlock.unlock();
        }
    }

    public static UploadResult upload(PushProvincialUploadParam param) {
        login();
        try {
            rlock.lock();
            if (StrUtil.isBlank(tnt) || StrUtil.isBlank(refTnt)) {
                return new UploadResult();
            }
            return API.upload(param, new TokenParam().setTnt(tnt).setRefTnt(refTnt));
        } finally {
            rlock.unlock();
        }
    }

    public static void login() {
        try {
            wlock.lock();
            long now = System.currentTimeMillis() / 1000;
            if (StrUtil.isBlank(refTnt) || StrUtil.isBlank(tnt)) {
                HsoaResult<LoginResult> loginResult = API.login(new LoginParam()
                        .setUserName(hsoaProperties.getUsername())
                        .setPassword(hsoaProperties.getPassword())
                );
                if (loginResult.isSuccess()) {
                    LoginResult data = loginResult.getData();
                    refTnt = data.getRefTnt();
                    tnt = data.getTnt();
                    lastLoginTime = now;
                } else {
                    refTnt = "";
                    tnt = "";
                    log.error("政务平台登录失败");
                }
            } else if (now - lastLoginTime > hsoaProperties.getExpire() - 60) {
                HsoaResult<LoginResult> loginResult = API.refreshToken(new RefreshTokenParam().setRefTnt(refTnt));
                if (loginResult.isSuccess()) {
                    LoginResult data = loginResult.getData();
                    refTnt = data.getRefTnt();
                    tnt = data.getTnt();
                    lastLoginTime = now;
                } else {
                    refTnt = "";
                    tnt = "";
                    log.error("政务平台登录失败");
                }
            }
        } catch (Exception e) {
            refTnt = "";
            tnt = "";
            log.error("政务平台登录失败", e);
        } finally {
            wlock.unlock();
        }
    }

    public synchronized static void relogin() {
        if (StrUtil.isBlank(refTnt) || StrUtil.isBlank(tnt)) {
            log.info("无需重置登录TOKEN");
            return;
        }
        try {
            wlock.lock();
            log.info("重置登录TOKEN");
            refTnt = "";
            tnt = "";
            login();
        } finally {
            wlock.unlock();
        }
    }
}
