package com.streamplayer;

import java.security.cert.X509Certificate;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.Dns;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.dnsoverhttps.DnsOverHttps;

/**
 * Utilidad centralizada para configuración de red con múltiples servidores DNS over HTTPS.
 * Implementa fallback progresivo: Google -> Cloudflare -> AdGuard -> Quad9 -> Sistema
 */
public class NetworkUtils {

    private static final OkHttpClient CLIENT;
    private static final String USER_AGENT = "Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36";

    // URLs de servidores DNS over HTTPS
    private static final String GOOGLE_DOH_URL = "https://dns.google/dns-query";
    private static final String CLOUDFLARE_DOH_URL = "https://cloudflare-dns.com/dns-query";
    private static final String ADGUARD_DOH_URL = "https://dns.adguard-dns.com/dns-query";
    private static final String QUAD9_DOH_URL = "https://dns.quad9.net/dns-query";

    static {
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectTimeout(20, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS)
                .followRedirects(true)
                .followSslRedirects(true)
                .retryOnConnectionFailure(true);

        try {
            // Configurar para aceptar todos los certificados SSL (útil para diagnosticar problemas de ISP)
            // NOTA: Esto es temporal para diagnosticar si hay problemas de certificados MITM
            final TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {}
                    @Override
                    public void checkServerTrusted(X509Certificate[] chain, String authType) {}
                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[]{};
                    }
                }
            };

            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            
            builder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0]);
            builder.hostnameVerifier((hostname, session) -> true);

            // Cliente bootstrap para resolver los dominios de DNS
            OkHttpClient bootstrap = new OkHttpClient.Builder()
                    .connectTimeout(10, TimeUnit.SECONDS)
                    .retryOnConnectionFailure(true)
                    .build();

            // 1. Google DNS over HTTPS (Primario)
            final DnsOverHttps googleDns = new DnsOverHttps.Builder()
                    .client(bootstrap)
                    .url(HttpUrl.get(GOOGLE_DOH_URL))
                    .bootstrapDnsHosts(
                            getByIp("8.8.8.8"),
                            getByIp("8.8.4.4"))
                    .includeIPv6(false)
                    .build();

            // 2. Cloudflare DNS over HTTPS (Secundario)
            final DnsOverHttps cloudflareDns = new DnsOverHttps.Builder()
                    .client(bootstrap)
                    .url(HttpUrl.get(CLOUDFLARE_DOH_URL))
                    .bootstrapDnsHosts(
                            getByIp("1.1.1.1"),
                            getByIp("1.0.0.1"))
                    .includeIPv6(false)
                    .build();

            // 3. AdGuard DNS over HTTPS (Terciario)
            final DnsOverHttps adGuardDns = new DnsOverHttps.Builder()
                    .client(bootstrap)
                    .url(HttpUrl.get(ADGUARD_DOH_URL))
                    .bootstrapDnsHosts(
                            getByIp("94.140.14.14"),
                            getByIp("94.140.15.15"))
                    .includeIPv6(false)
                    .build();

            // 4. Quad9 DNS over HTTPS (Cuaternario)
            final DnsOverHttps quad9Dns = new DnsOverHttps.Builder()
                    .client(bootstrap)
                    .url(HttpUrl.get(QUAD9_DOH_URL))
                    .bootstrapDnsHosts(
                            getByIp("9.9.9.9"),
                            getByIp("149.112.112.112"))
                    .includeIPv6(false)
                    .build();

            // Configurar DNS con fallback: Google -> Cloudflare -> AdGuard -> Quad9 -> Sistema
            builder.dns(new Dns() {
                @Override
                public List<InetAddress> lookup(String hostname) throws UnknownHostException {
                    // Intento 1: Google DNS
                    try {
                        List<InetAddress> result = googleDns.lookup(hostname);
                        if (result != null && !result.isEmpty()) return result;
                    } catch (Exception ignored) {
                        // Falló Google, continuar
                    }

                    // Intento 2: Cloudflare DNS
                    try {
                        List<InetAddress> result = cloudflareDns.lookup(hostname);
                        if (result != null && !result.isEmpty()) return result;
                    } catch (Exception ignored) {
                        // Falló Cloudflare, continuar
                    }

                    // Intento 3: AdGuard DNS
                    try {
                        List<InetAddress> result = adGuardDns.lookup(hostname);
                        if (result != null && !result.isEmpty()) return result;
                    } catch (Exception ignored) {
                        // Falló AdGuard, continuar
                    }

                    // Intento 4: Quad9 DNS
                    try {
                        List<InetAddress> result = quad9Dns.lookup(hostname);
                        if (result != null && !result.isEmpty()) return result;
                    } catch (Exception ignored) {
                        // Falló Quad9, continuar
                    }

                    // Intento 5: DNS del Sistema (Fallback final)
                    try {
                        return Dns.SYSTEM.lookup(hostname);
                    } catch (UnknownHostException e) {
                        throw e;
                    }
                }
            });

        } catch (Exception e) {
            // Si algo falla en la configuración DNS, usamos por defecto (implícito en el builder)
            System.out.println("Error configurando DNS over HTTPS: " + e.getMessage());
        }

        CLIENT = builder.build();
    }

    private static InetAddress getByIp(String ip) throws UnknownHostException {
        return InetAddress.getByName(ip);
    }

    public static OkHttpClient getClient() {
        return CLIENT;
    }

    public static String getUserAgent() {
        return USER_AGENT;
    }
}
