package com.foxx.androidcast.live;

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

import com.foxx.androidcast.crash.CrashSettingsStore;
import com.foxx.androidcast.network.BackendEndpoints;

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

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/** Polls BE for active live cast sessions to highlight casting peers in discovery UI. */
public final class LiveCastPeerTracker {
    private static final String TAG = "LiveCastPeerTracker";
    private static final long POLL_INTERVAL_SEC = 45L;
    private static final int HTTP_TIMEOUT_MS = 15_000;

    public interface Listener {
        void onLivePeersUpdated(Set<String> liveDeviceIds, Set<String> liveUsernames);
    }

    private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor(r -> {
        Thread t = new Thread(r, "live-cast-peer-poll");
        t.setDaemon(true);
        return t;
    });
    private static final AtomicReference<ScheduledFuture<?>> POLL_TASK = new AtomicReference<>();
    private static final AtomicReference<Listener> LISTENER = new AtomicReference<>();
    private static final AtomicReference<String> API_URL = new AtomicReference<>("");

    private LiveCastPeerTracker() {}

    public static void start(Context context, Listener listener) {
        if (context == null || listener == null) {
            return;
        }
        LISTENER.set(listener);
        API_URL.set(resolveActiveUrl(context.getApplicationContext()));
        ScheduledFuture<?> prev = POLL_TASK.getAndSet(
                EXECUTOR.scheduleAtFixedRate(LiveCastPeerTracker::pollOnce, 0L, POLL_INTERVAL_SEC, TimeUnit.SECONDS));
        if (prev != null) {
            prev.cancel(false);
        }
    }

    public static void stop() {
        ScheduledFuture<?> prev = POLL_TASK.getAndSet(null);
        if (prev != null) {
            prev.cancel(false);
        }
        LISTENER.set(null);
    }

    private static void pollOnce() {
        Listener listener = LISTENER.get();
        String url = API_URL.get();
        if (listener == null || url == null || url.isEmpty()) {
            return;
        }
        try {
            Set<String> deviceIds = new HashSet<>();
            Set<String> usernames = new HashSet<>();
            JSONObject payload = getJson(url + "?action=active");
            if (payload != null && payload.optBoolean("ok", false)) {
                JSONArray sessions = payload.optJSONArray("sessions");
                if (sessions != null) {
                    for (int i = 0; i < sessions.length(); i++) {
                        JSONObject row = sessions.optJSONObject(i);
                        if (row == null) {
                            continue;
                        }
                        String status = row.optString("status", "");
                        if (!"live".equals(status) && !"intent".equals(status)) {
                            continue;
                        }
                        String deviceId = row.optString("device_id", "");
                        if (!deviceId.isEmpty()) {
                            deviceIds.add(deviceId);
                        }
                        String username = row.optString("owner_username", "");
                        if (!username.isEmpty()) {
                            usernames.add(username.toLowerCase(Locale.US));
                        }
                    }
                }
            }
            listener.onLivePeersUpdated(Collections.unmodifiableSet(deviceIds),
                    Collections.unmodifiableSet(usernames));
        } catch (Exception e) {
            Log.w(TAG, "poll failed: " + e.getMessage());
        }
    }

    private static String resolveActiveUrl(Context context) {
        String upload = CrashSettingsStore.load(context).uploadUrl;
        if (upload != null && !upload.trim().isEmpty()) {
            String base = BackendEndpoints.normalizeCrashesUrl(upload.trim());
            if (base.contains("/api/upload.php")) {
                return base.replace("/api/upload.php", "/api/live_cast.php");
            }
            if (base.endsWith("/")) {
                return base + "api/live_cast.php";
            }
            return base + "/api/live_cast.php";
        }
        return BackendEndpoints.CRASHES_BASE + "/api/live_cast.php";
    }

    private static JSONObject getJson(String url) throws Exception {
        HttpURLConnection c = (HttpURLConnection) new URL(url).openConnection();
        c.setRequestMethod("GET");
        c.setConnectTimeout(HTTP_TIMEOUT_MS);
        c.setReadTimeout(HTTP_TIMEOUT_MS);
        int code = c.getResponseCode();
        String text = readBody(c);
        c.disconnect();
        if (code < 200 || code >= 300) {
            throw new IllegalStateException("http_" + code);
        }
        return new JSONObject(text);
    }

    private static String readBody(HttpURLConnection c) {
        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(c.getInputStream(), StandardCharsets.UTF_8))) {
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line);
                if (sb.length() > 16384) {
                    break;
                }
            }
            return sb.toString();
        } catch (Exception e) {
            return "";
        }
    }
}
