package com.foxx.androidcast.remoteaccess;

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

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

import org.json.JSONObject;

import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Outbound reverse SSH (-R) to bastion. Alpha path — no {@link android.net.VpnService}.
 */
public final class ReverseSshTunnelBridge {
    private static final String TAG = "RsshTunnelBridge";
    private static final int CONNECT_TIMEOUT_MS = 30_000;

    private static volatile Thread worker;
    private static volatile Session session;
    private static final AtomicBoolean connected = new AtomicBoolean(false);

    private ReverseSshTunnelBridge() {}

    public static boolean applyConfig(Context context, JSONObject creds) {
        if (creds == null) {
            return false;
        }
        tearDown(context);
        String host = creds.optString("bastion_host", "");
        int port = creds.optInt("bastion_port", 443);
        String user = creds.optString("username", "");
        String pass = creds.optString("password", "");
        int remotePort = creds.optInt("remote_bind_port", 0);
        String localHost = creds.optString("local_forward_host", "127.0.0.1");
        int localPort = creds.optInt("local_forward_port", 8022);
        if (host.isEmpty() || user.isEmpty() || pass.isEmpty() || remotePort <= 0) {
            Log.w(TAG, "incomplete RSSH credentials");
            return false;
        }
        CountDownLatch connectedLatch = new CountDownLatch(1);
        AtomicBoolean ok = new AtomicBoolean(false);
        worker = new Thread(() -> {
            try {
                JSch jsch = new JSch();
                Session s = jsch.getSession(user, host, port);
                s.setPassword(pass);
                Properties cfg = new Properties();
                cfg.put("StrictHostKeyChecking", "no");
                s.setConfig(cfg);
                s.setServerAliveInterval(30_000);
                s.connect(CONNECT_TIMEOUT_MS);
                s.setPortForwardingR(remotePort, localHost, localPort);
                session = s;
                connected.set(true);
                ok.set(true);
                connectedLatch.countDown();
                Log.i(TAG, "RSSH -R " + remotePort + " -> " + localHost + ":" + localPort);
                while (s.isConnected() && !Thread.currentThread().isInterrupted()) {
                    Thread.sleep(5_000);
                }
            } catch (Exception e) {
                Log.w(TAG, "RSSH tunnel failed: " + e.getMessage());
                connectedLatch.countDown();
            } finally {
                connected.set(false);
                Session s = session;
                session = null;
                if (s != null) {
                    try {
                        s.disconnect();
                    } catch (Exception ignored) {
                    }
                }
            }
        }, "androidcast-rssh");
        worker.setDaemon(true);
        worker.start();
        try {
            if (!connectedLatch.await(CONNECT_TIMEOUT_MS + 5_000L, TimeUnit.MILLISECONDS)) {
                Log.w(TAG, "RSSH connect timed out");
                return false;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
        return ok.get();
    }

    public static void tearDown(Context context) {
        Thread w = worker;
        worker = null;
        Session s = session;
        session = null;
        connected.set(false);
        if (s != null) {
            try {
                s.disconnect();
            } catch (Exception ignored) {
            }
        }
        if (w != null) {
            w.interrupt();
        }
    }

    public static boolean isConnected() {
        Session s = session;
        return s != null && s.isConnected();
    }
}
