package com.miraclegarden.smsmessage.mmp;

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

import com.miraclegarden.smsmessage.AppConfig;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * 把手机本地红包台全量同步到 PC 调试台，方便电脑打开 /mmp 查看。
 */
public final class MmpSyncClient {

    private static final String TAG = "MmpSyncClient";
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static final OkHttpClient CLIENT = new OkHttpClient.Builder()
            .connectTimeout(5, TimeUnit.SECONDS)
            .writeTimeout(8, TimeUnit.SECONDS)
            .readTimeout(8, TimeUnit.SECONDS)
            .build();
    private static final ExecutorService EXEC = Executors.newSingleThreadExecutor();
    private static final AtomicBoolean IN_FLIGHT = new AtomicBoolean(false);
    private static volatile long sLastSyncAt;

    public interface Callback {
        void onDone(boolean ok, String message);
    }

    private MmpSyncClient() {
    }

    public static void syncToPc(Context context) {
        syncToPc(context, null);
    }

    public static void syncToPc(Context context, Callback callback) {
        if (context == null || !AppConfig.ENABLE_DEBUG_FORWARD) {
            if (callback != null) {
                callback.onDone(false, "调试转发未开启");
            }
            return;
        }
        final Context app = context.getApplicationContext();
        EXEC.execute(() -> {
            if (!IN_FLIGHT.compareAndSet(false, true)) {
                if (callback != null) {
                    callback.onDone(false, "同步进行中");
                }
                return;
            }
            try {
                JSONArray packets = MmpPacketStore.exportJsonArray(app);
                JSONObject body = new JSONObject();
                body.put("packets", packets);
                body.put("device", "android");
                body.put("syncedAt", System.currentTimeMillis());
                JSONObject hook = new JSONObject();
                MmpHookStatus.ensureLoaded(app);
                hook.put("liveCode", MmpHookStatus.liveVersionCode(app));
                hook.put("liveName", MmpHookStatus.liveVersionName(app));
                hook.put("liveAt", MmpHookStatus.lastAliveAt(app));
                hook.put("installedCode", MmpHookStatus.installedVersionCode(app));
                hook.put("installedName", MmpHookStatus.installedVersionName(app));
                body.put("hookStatus", hook);
                String payload = body.toString();

                boolean anyOk = false;
                String lastErr = "调试台不可达";
                String lastOkMsg = "";
                for (String base : AppConfig.DEBUG_SERVER_URLS) {
                    if (TextUtils.isEmpty(base)) {
                        continue;
                    }
                    try {
                        Request req = new Request.Builder()
                                .url(base.replaceAll("/$", "") + "/api/mmp/sync")
                                .post(RequestBody.create(payload, JSON))
                                .build();
                        try (Response resp = CLIENT.newCall(req).execute()) {
                            String respBody = resp.body() != null ? resp.body().string() : "";
                            if (resp.isSuccessful()) {
                                anyOk = true;
                                lastOkMsg = "已同步 " + packets.length() + " 个红包到电脑";
                                Log.i(TAG, "sync ok -> " + base + " " + respBody);
                            } else {
                                lastErr = "HTTP " + resp.code();
                            }
                        }
                    } catch (Exception e) {
                        lastErr = e.getMessage();
                        Log.w(TAG, "sync fail " + base + ": " + lastErr);
                    }
                }
                sLastSyncAt = System.currentTimeMillis();
                if (callback != null) {
                    if (anyOk) {
                        callback.onDone(true, lastOkMsg);
                    } else {
                        callback.onDone(false, lastErr != null ? lastErr : "同步失败");
                    }
                }
            } catch (Exception e) {
                Log.e(TAG, "sync error", e);
                if (callback != null) {
                    callback.onDone(false, e.getMessage());
                }
            } finally {
                IN_FLIGHT.set(false);
            }
        });
    }

    /** 距上次同步超过 cooldownMs 才再同步。 */
    public static void syncIfStale(Context context, long cooldownMs) {
        if (System.currentTimeMillis() - sLastSyncAt < cooldownMs) {
            return;
        }
        syncToPc(context, null);
    }
}
