package com.ttstd.dialer.manager;

import android.annotation.SuppressLint;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.jeremyliao.liveeventbus.LiveEventBus;
import com.qweather.sdk.Callback;
import com.qweather.sdk.JWTGenerator;
import com.qweather.sdk.QWeather;
import com.qweather.sdk.basic.Lang;
import com.qweather.sdk.basic.Unit;
import com.qweather.sdk.parameter.weather.WeatherParameter;
import com.qweather.sdk.response.weather.WeatherDailyResponse;
import com.qweather.sdk.response.weather.WeatherHourlyResponse;
import com.qweather.sdk.response.weather.WeatherNowResponse;
import com.ttstd.dialer.BuildConfig;
import com.ttstd.dialer.bean.CityInfo;
import com.ttstd.dialer.config.CommonConfig;
import com.ttstd.dialer.utils.Logger;
import com.ttstd.dialer.utils.NativeUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableEmitter;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;

public class WeatherManager {
    private static final String TAG = "WeatherManager";

    @SuppressLint("StaticFieldLeak")
    private static WeatherManager INSTANCE;
    private Context mContext;
    private QWeather mQWeather;
    private Map<String, String> LocationIDMap = new HashMap<>();
    private boolean loadCsvFinish = false;
    private String mAdCode;


    private WeatherManager(Context context) {
        this.mContext = context.getApplicationContext();
        initCsv();
        try {
            // 通过SDK提供的JWTGenerator设置令牌生成器，其实现自TokenGenerator接口
            JWTGenerator jwt = new JWTGenerator(NativeUtils.getQWeatherPrivateKey(), // 私钥
                    NativeUtils.getQWeatherProjectId(), // 项目ID
                    NativeUtils.getQWeatherCredentialId()); // 凭据ID
            mQWeather = QWeather.getInstance(context, NativeUtils.getQWeatherUrl()) // 初始化服务地址
                    .setLogEnable(BuildConfig.DEBUG)  // 启用调试日志（生产环境建议设置为 false）
                    .setTokenGenerator(jwt);
        } catch (Throwable e) {
            Log.e(TAG, "QWeatherUtils: " + e.getMessage());
            e.printStackTrace();
        }
    }

    public static void init(Context context) {
        if (INSTANCE == null) {
            INSTANCE = new WeatherManager(context);
        }
    }

    public static WeatherManager getInstance() {
        if (INSTANCE == null) {
            throw new IllegalStateException("You must be init WeatherManager first");
        }
        return INSTANCE;
    }

    public QWeather getQWeather() {
        return mQWeather;
    }

    public void setAdCode(String adCode) {
        mAdCode = adCode;
        if (loadCsvFinish) {
            if (!TextUtils.isEmpty(adCode)) {
                String locationId = LocationIDMap.get(adCode);
                Logger.e(this, TAG, "setAdCode: locationId = " + locationId);
                LiveEventBus.get(CommonConfig.LOCATION_ID_CHANGED_KEY)
                        .post(locationId);
            }
        }
    }

    private void initCsv() {
        Observable.create(new ObservableOnSubscribe<List<CityInfo>>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<List<CityInfo>> emitter) throws Throwable {
                long time = System.currentTimeMillis();
                List<CityInfo> cityInfos = CsvDeserializer.deserializeFromAssets(mContext, "China-City-List-latest.csv");
                Log.e(TAG, "subscribe: deserializeFromAssets time = " + (System.currentTimeMillis() - time) + "ms");
                emitter.onNext(cityInfos);
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<List<CityInfo>>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        Logger.e(TAG, "initCsv", "onSubscribe: ");
                    }

                    @Override
                    public void onNext(@NonNull List<CityInfo> cityInfos) {
                        Logger.e(TAG, "initCsv", "onNext: cityInfos size = " + cityInfos.size());
                        Logger.e(TAG, "initCsv", "onNext: cityInfos 0 info = " + cityInfos.get(0));

                        LocationIDMap = cityInfos.stream()
                                .filter(cityInfo -> cityInfo.getLocation_ID() != null) // 过滤掉 value 为 null 的条目
                                .collect(Collectors.toMap(CityInfo::getAD_code, CityInfo::getLocation_ID, (oldVal, newVal) -> oldVal, HashMap::new));

                        Logger.e(TAG, "initCsv", "onNext: LocationIDMap size = " + LocationIDMap.size());
                        onComplete();
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        Logger.e(TAG, "initCsv", "onError: " + e.getMessage());
                    }

                    @Override
                    public void onComplete() {
                        Logger.e(TAG, "initCsv", "onComplete: ");
                        loadCsvFinish = true;
                        if (!TextUtils.isEmpty(mAdCode)) {
                            String locationId = LocationIDMap.get(mAdCode);
                            Logger.e(TAG, "initCsv", "onComplete: locationId = " + locationId);
                            LiveEventBus.get(CommonConfig.LOCATION_ID_CHANGED_KEY)
                                    .post(locationId);
                        }
                    }
                });
    }

    private String getLocationID(String adCode) {
        if (LocationIDMap != null) {
            return LocationIDMap.get(adCode);
        }
        return "";
    }

    public void getWeatherNow(String adCode, Callback<WeatherNowResponse> callback) {
        String locationID = getLocationID(adCode);
        Log.e(TAG, "getWeatherNow: locationID = " + locationID);
        WeatherParameter parameter = new WeatherParameter(locationID)
                .lang(Lang.ZH_HANS)
                .unit(Unit.METRIC);
        mQWeather.weatherNow(parameter, callback);
    }

    public void getWeather24h(String adCode, Callback<WeatherHourlyResponse> callback) {
        String locationID = getLocationID(adCode);
        Log.e(TAG, "getWeatherNow: locationID = " + locationID);
        WeatherParameter parameter = new WeatherParameter(locationID)
                .lang(Lang.ZH_HANS)
                .unit(Unit.METRIC);
        mQWeather.weather24h(parameter, callback);
    }

    public void getWeather10D(String adCode, Callback<WeatherDailyResponse> callback) {
        String locationID = getLocationID(adCode);
        Log.e(TAG, "getWeather10D: locationID = " + locationID);
        WeatherParameter parameter = new WeatherParameter(locationID)
                .lang(Lang.ZH_HANS)
                .unit(Unit.METRIC);
        mQWeather.weather10d(parameter, callback);
    }


}
