package com.anythink.reactnative.init;

import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;

import com.thinkup.core.api.TUAdFilter;
import com.thinkup.core.api.TUAreaCallback;
import com.thinkup.core.api.TUGDPRConsentDismissListener;
import com.thinkup.core.api.TUSDK;
import com.thinkup.core.api.TUSDKInitListener;
import com.thinkup.core.api.TUSharedPlacementConfig;
import com.thinkup.core.api.NetTrafficeCallback;
import com.thinkup.debug.api.TUDebuggerUITest;
import com.anythink.reactnative.event.ATReactNativeEventEmitter;
import com.anythink.reactnative.utils.BridgeJsonMapUtil;
import com.anythink.reactnative.utils.Const;
import com.anythink.reactnative.utils.MsgTools;
import com.anythink.reactnative.utils.RNMapUtil;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;

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

/**
* Init/Core routing.
* Only forwarding, calling the real `com.thinkup.core.api.TUSDK`. Get it from Context/Activity bridge.
 */
public class ATInitManager {

    private static volatile ATInitManager sInstance;
    private final Handler mMainHandler = new Handler(Looper.getMainLooper());
    private volatile ReactApplicationContext mReactContext;
    private volatile boolean mInitialized = false;

    /** Whether init was called (SDK_NOT_INITIALIZED gate for rewarded etc. ad bridge methods). */
    public boolean isInitialized() {
        return mInitialized;
    }

    private ATInitManager() {
    }

    public static ATInitManager getInstance() {
        if (sInstance == null) {
            synchronized (ATInitManager.class) {
                if (sInstance == null) {
                    sInstance = new ATInitManager();
                }
            }
        }
        return sInstance;
    }

    public void setReactContext(ReactApplicationContext reactContext) {
        mReactContext = reactContext;
    }

    private Context appContext() {
        return mReactContext != null ? mReactContext.getApplicationContext() : null;
    }

    private Activity currentActivity() {
        return mReactContext != null ? mReactContext.getCurrentActivity() : null;
    }

    // -- Init / version --

    public void initAnyThinkSDK(String appId, String appKey) {
        MsgTools.printMsg("initAnyThinkSDK appId=" + appId);
        mInitialized = true;
// Development framework identification: report os_fw=5 (React Native)
        TUSDK.setSystemDevFragmentType("5");
        Context ctx = appContext();
        if (ctx == null) {
            return;
        }
// The init is completed and the InitCallName event is returned to JS (light up the upstream event channel; P1-F06)
        TUSDK.init(ctx, appId, appKey, null, new TUSDKInitListener() {
            @Override
            public void onSuccess() {
                MsgTools.printMsg("init onSuccess");
                ATReactNativeEventEmitter.getInstance().sendCallback(
                        Const.CallbackMethodCall.InitCallName,
                        Const.InitCallback.sdkInitSuccessCallbackKey, "", null, null, null);
            }

            @Override
            public void onFail(String errorMsg) {
                MsgTools.printMsg("init onFail: " + errorMsg);
                ATReactNativeEventEmitter.getInstance().sendCallback(
                        Const.CallbackMethodCall.InitCallName,
                        Const.InitCallback.sdkInitFailCallbackKey, "", null, errorMsg, null);
            }
        });
    }

    public void start() {
        MsgTools.printMsg("start");
        TUSDK.start();
    }

    public String getSDKVersionName() {
        return TUSDK.getSDKVersionName();
    }

    // -- Logging / channel / custom params --

    public void setLogEnabled(boolean enabled) {
// Double log opening: first open the bridge layer MsgTools (make sure the following line is visible), then open the SDK network log
        MsgTools.setLogDebug(enabled);
        TUSDK.setNetworkLogDebug(enabled);
//Read back the SDK flag to prove that it is indeed written into the SDKContext
        MsgTools.printMsg("setLogEnabled " + enabled
                + " -> TUSDK.isNetworkLogDebug()=" + TUSDK.isNetworkLogDebug());
    }

    public void setChannelStr(String channel) {
        MsgTools.printMsg("setChannelStr " + channel);
        TUSDK.setChannel(channel);
    }

    public void setCustomDataDic(ReadableMap customMap) {
        MsgTools.printMsg("setCustomDataDic customMap=" + RNMapUtil.readableMapToJsonString(customMap));
        TUSDK.initCustomMap(RNMapUtil.readableMapToHashMap(customMap));
    }

    public void setPlacementCustomData(String placementId, ReadableMap customMap) {
        MsgTools.printMsg("setPlacementCustomData placementId=" + placementId
                + " customMap=" + RNMapUtil.readableMapToJsonString(customMap));
        TUSDK.initPlacementCustomMap(placementId, RNMapUtil.readableMapToHashMap(customMap));
    }

    // -- GDPR / privacy --

    public void getGDPRLevel(Promise promise) {
        Context ctx = appContext();
        if (ctx == null) {
            promise.reject(Const.BridgeError.SDK_NOT_INITIALIZED, "react context null");
            return;
        }
        promise.resolve(TUSDK.getGDPRDataLevel(ctx));
    }

    public void setDataConsentSet(int level) {
        MsgTools.printMsg("setDataConsentSet " + level);
        Context ctx = appContext();
        if (ctx != null) {
            TUSDK.setGDPRUploadDataLevel(ctx, level);
        }
    }

    public void showGDPRConsentDialog(final String appId) {
        MsgTools.printMsg("showGDPRConsentDialog appId=" + appId);
        mMainHandler.post(new Runnable() {
            @Override
            public void run() {
                Activity activity = currentActivity();
                if (activity == null) {
                    MsgTools.printMsg("showGDPRConsentDialog: currentActivity null, abort");
                    return;
                }
                TUGDPRConsentDismissListener listener = new TUGDPRConsentDismissListener() {
                    @Override
                    public void onDismiss(ConsentDismissInfo info) {
                        Map<String, Object> extraDic = new HashMap<>();
                        if (info != null) {
                            extraDic.put("infoMsg", info.getInfoMsg());
                            extraDic.put("dismissType", info.getDismissType());
                        }
                        ATReactNativeEventEmitter.getInstance().sendCallback(
                                Const.CallbackMethodCall.InitCallName,
                                Const.InitCallback.consentDismissCallbackKey,
                                "", extraDic, null, null);
                    }
                };
                if (!TextUtils.isEmpty(appId)) {
                    MsgTools.printMsg("showGDPRConsentDialog: overseas TPN ignores appId param");
                }
                TUSDK.showGDPRConsentDialog(activity, listener);
            }
        });
    }

    // -- Filter / strategy / debug --

    public void putFilter(String placementId, ReadableMap filterSpec) {
        MsgTools.printMsg("putFilter placementId=" + placementId
                + " filterSpec=" + RNMapUtil.readableMapToJsonString(filterSpec));
        try {
// Complex nested parameters: ReadableMap → JSON string → BridgeJsonMapUtil (reuse existing JSON parsing)
            String json = RNMapUtil.readableMapToJsonString(filterSpec);
            TUAdFilter filter = BridgeJsonMapUtil.waterfallFilterFromGroupsJson(json);
            if (filter != null) {
                TUSDK.putFilter(placementId, filter);
            }
        } catch (Throwable e) {
            MsgTools.printMsg("putFilter error: " + e.getMessage());
        }
    }

    public void removeFilters() {
        MsgTools.printMsg("removeFilters");
        TUSDK.removeFilters();
    }

    public void removeFilterWithPlacementId(String placementId) {
        MsgTools.printMsg("removeFilterWithPlacementId placementId=" + placementId);
        TUSDK.removeFilterWithPlacementId(placementId);
    }

    public void setAdSourcePrivacyPolicy(String policyJson) {
        MsgTools.printMsg("setAdSourcePrivacyPolicy: "
                + (policyJson == null ? "null" : ("len=" + policyJson.length())));
        if (TextUtils.isEmpty(policyJson)) {
            AdSourcePrivacyPolicyStore.setPolicyJson(null);
        } else {
            AdSourcePrivacyPolicyStore.setPolicyJson(policyJson);
        }
    }

    public void showDebuggerUI(final String debugKey) {
        MsgTools.printMsg("showDebuggerUI");
        final Context ctx = appContext();
        if (ctx == null) {
            return;
        }
        mMainHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    TUDebuggerUITest.showDebuggerUI(ctx, debugKey);
                } catch (Throwable e) {
                    MsgTools.printMsg("showDebuggerUI error: " + e.getMessage());
                }
            }
        });
    }

    // -- TUSDK extras --

    private static List<String> toStringList(ReadableArray arr) {
        List<String> list = new ArrayList<>();
        if (arr != null) {
            for (int i = 0; i < arr.size(); i++) {
                list.add(arr.getString(i));
            }
        }
        return list;
    }

    public void showGDPRConsentSecondDialog(final String appId) {
        MsgTools.printMsg("showGDPRConsentSecondDialog appId=" + appId);
        mMainHandler.post(new Runnable() {
            @Override
            public void run() {
                Activity activity = currentActivity();
                if (activity == null) {
                    MsgTools.printMsg("showGDPRConsentSecondDialog: activity null, abort");
                    return;
                }
                TUGDPRConsentDismissListener listener = new TUGDPRConsentDismissListener() {
                    @Override
                    public void onDismiss(ConsentDismissInfo info) {
                        Map<String, Object> extraDic = new HashMap<>();
                        if (info != null) {
                            extraDic.put("infoMsg", info.getInfoMsg());
                            extraDic.put("dismissType", info.getDismissType());
                        }
                        ATReactNativeEventEmitter.getInstance().sendCallback(
                                Const.CallbackMethodCall.InitCallName,
                                Const.InitCallback.consentDismissCallbackKey, "", extraDic, null, null);
                    }
                };
                TUSDK.showGDPRConsentSecondDialog(activity, listener, appId != null ? appId : "");
            }
        });
    }

    public void showGdprAuth() {
        MsgTools.printMsg("showGdprAuth");
        Context ctx = appContext();
        if (ctx != null) {
            TUSDK.showGdprAuth(ctx);
        }
    }

    public void checkIsEuTraffic(final Promise promise) {
        Context ctx = appContext();
        if (ctx == null) {
            promise.resolve(false);
            return;
        }
        TUSDK.checkIsEuTraffic(ctx, new NetTrafficeCallback() {
            @Override
            public void onResultCallback(boolean isEUTraffic) {
                promise.resolve(isEUTraffic);
            }

            @Override
            public void onErrorCallback(String msg) {
                MsgTools.printMsg("checkIsEuTraffic error: " + msg);
                promise.resolve(false);
            }
        });
    }

    public void isEUTraffic(Promise promise) {
        Context ctx = appContext();
        promise.resolve(ctx != null && TUSDK.isEUTraffic(ctx));
    }

    public void deniedUploadDeviceInfo(ReadableArray keys) {
        MsgTools.printMsg("deniedUploadDeviceInfo deviceInfoKeys="
                + RNMapUtil.readableArrayToJsonString(keys));
        List<String> list = toStringList(keys);
        TUSDK.deniedUploadDeviceInfo(list.toArray(new String[0]));
    }

    public void setPersonalizedAdStatus(int status) {
        MsgTools.printMsg("setPersonalizedAdStatus " + status);
        TUSDK.setPersonalizedAdStatus(status);
    }

    public void setFilterAdSourceIdList(String placementId, ReadableArray list) {
        MsgTools.printMsg("setFilterAdSourceIdList placementId=" + placementId
                + " adSourceIdList=" + RNMapUtil.readableArrayToJsonString(list));
        TUSDK.setFilterAdSourceIdList(placementId, toStringList(list));
    }

    public void setFilterNetworkFirmIdList(String placementId, ReadableArray list) {
        MsgTools.printMsg("setFilterNetworkFirmIdList placementId=" + placementId
                + " networkFirmIdList=" + RNMapUtil.readableArrayToJsonString(list));
        TUSDK.setFilterNetworkFirmIdList(placementId, toStringList(list));
    }

    public void setForbidNetworkFirmIdList(ReadableArray list) {
        MsgTools.printMsg("setForbidNetworkFirmIdList networkFirmIdList="
                + RNMapUtil.readableArrayToJsonString(list));
        TUSDK.setForbidNetworkFirmIdList(toStringList(list));
    }

    public void setForbidShowNetworkFirmIdList(String placementId, ReadableArray list) {
        MsgTools.printMsg("setForbidShowNetworkFirmIdList placementId=" + placementId
                + " networkFirmIdList=" + RNMapUtil.readableArrayToJsonString(list));
        TUSDK.setForbidShowNetworkFirmIdList(placementId, toStringList(list));
    }

    public void setAllowedShowNetworkFirmIdList(String placementId, ReadableArray list) {
        MsgTools.printMsg("setAllowedShowNetworkFirmIdList placementId=" + placementId
                + " networkFirmIdList=" + RNMapUtil.readableArrayToJsonString(list));
        TUSDK.setAllowedShowNetworkFirmIdList(placementId, toStringList(list));
    }

    public void setRiskFilterNetworkFirmIdList(int risk, ReadableArray list) {
        MsgTools.printMsg("setRiskFilterNetworkFirmIdList risk=" + risk
                + " networkFirmIdList=" + RNMapUtil.readableArrayToJsonString(list));
        TUSDK.setRiskFilterNetworkFirmIdList(risk, toStringList(list));
    }

    public void getArea(final Promise promise) {
        TUSDK.getArea(new TUAreaCallback() {
            @Override
            public void onResultCallback(String area) {
                promise.resolve(area);
            }

            @Override
            public void onErrorCallback(String msg) {
                MsgTools.printMsg("getArea error: " + msg);
                promise.resolve("");
            }
        });
    }

    public void isCnSDK(Promise promise) {
        promise.resolve(TUSDK.isCnSDK());
    }

    public void setLocation(ReadableMap location) {
        if (location == null) {
            MsgTools.printMsg("setLocation location=null");
            return;
        }
        double latitude = location.hasKey("latitude") ? location.getDouble("latitude") : 0;
        double longitude = location.hasKey("longitude") ? location.getDouble("longitude") : 0;
        MsgTools.printMsg("setLocation latitude=" + latitude + " longitude=" + longitude);
        Location loc = new Location("");
        loc.setLatitude(latitude);
        loc.setLongitude(longitude);
        TUSDK.setLocation(loc);
    }

    public void setDeviceInformationData(ReadableMap data) {
        MsgTools.printMsg("setDeviceInformationData data=" + RNMapUtil.readableMapToJsonString(data));
        try {
            Map<String, Object> performanceData = RNMapUtil.deviceInformationDataFromReadableMap(data);
            MsgTools.printMsg("setDeviceInformationData normalized=" + performanceData);
            TUSDK.setDeviceInformationData(performanceData);
        } catch (Throwable e) {
            MsgTools.printMsg("setDeviceInformationData error: " + e.getMessage());
        }
    }

    public void integrationChecking() {
        MsgTools.printMsg("integrationChecking");
        Context ctx = appContext();
        if (ctx != null) {
            TUSDK.integrationChecking(ctx);
        }
    }

    public void isNetworkLogDebug(Promise promise) {
        promise.resolve(TUSDK.isNetworkLogDebug());
    }

    public void setChannelSource(int channelFrom) {
        MsgTools.printMsg("setChannelSource " + channelFrom);
        TUSDK.setChannelSource(channelFrom);
    }

    public void setLocalStrategyAssetPath(String path) {
        MsgTools.printMsg("setLocalStrategyAssetPath " + path);
        Context ctx = appContext();
        if (ctx != null) {
            TUSDK.setLocalStrategyAssetPath(ctx, path);
        }
    }

    public void setSharedPlacementConfig(ReadableMap config) {
        MsgTools.printMsg("setSharedPlacementConfig config=" + RNMapUtil.readableMapToJsonString(config));
        try {
            if (config == null) {
                return;
            }
            TUSharedPlacementConfig sharedConfig = BridgeJsonMapUtil.sharedPlacementConfigFromJson(
                    RNMapUtil.readableMapToJsonString(config));
            if (sharedConfig != null) {
                TUSDK.setSharedPlacementConfig(sharedConfig);
                MsgTools.printMsg("setSharedPlacementConfig: " + sharedConfig);
            } else {
                MsgTools.printMsg("setSharedPlacementConfig: parsed config is null");
            }
        } catch (Throwable e) {
            MsgTools.printMsg("setSharedPlacementConfig error: " + e.getMessage());
        }
    }
}
