package com.foxx.androidcast.remoteaccess.control;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.foxx.androidcast.IRemoteAccessControlHost;
import com.foxx.androidcast.IRemoteAccessControlService;
import com.foxx.androidcast.IVpnOperationCallback;

import java.util.UUID;

/**
 * Standalone RA control process ({@code com.foxx.androidcast:ra_control}) — HTTP UI + shell.
 */
public final class RemoteAccessControlService extends Service {
    private static final String TAG = "RaControlSvc";

    private final Object sessionLock = new Object();
    private volatile IRemoteAccessControlHost host;
    private volatile String authToken = "";
    private volatile int listenPort;
    private volatile boolean running;

    private HandlerThread workerThread;
    private Handler worker;
    private RemoteAccessControlHttpServer httpServer;

    private final IRemoteAccessControlService.Stub binder = new IRemoteAccessControlService.Stub() {
        @Override
        public void registerHost(IRemoteAccessControlHost hostRef) {
            host = hostRef;
        }

        @Override
        public void unregisterHost() {
            host = null;
        }

        @Override
        public void start(IVpnOperationCallback callback) {
            ensureWorker();
            worker.post(() -> startOnWorker(callback));
        }

        @Override
        public void stop(IVpnOperationCallback callback) {
            ensureWorker();
            worker.post(() -> {
                stopOnWorker();
                notifyOp(callback, true, null);
            });
        }

        @Override
        public boolean isRunning() {
            return running;
        }

        @Override
        public int getListenPort() {
            return listenPort;
        }

        @Override
        public String getAuthToken() {
            return authToken != null ? authToken : "";
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        httpServer = new RemoteAccessControlHttpServer(getApplicationContext(), new HostBridgeImpl());
        Log.i(TAG, "RA control process service created");
    }

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        stopOnWorker();
        if (workerThread != null) {
            workerThread.quitSafely();
            workerThread = null;
            worker = null;
        }
        super.onDestroy();
    }

    private void startOnWorker(IVpnOperationCallback callback) {
        synchronized (sessionLock) {
            if (running) {
                notifyOp(callback, true, null);
                return;
            }
            authToken = UUID.randomUUID().toString();
            httpServer.setAuthToken(authToken);
            try {
                listenPort = httpServer.start(0);
                running = true;
                Log.i(TAG, "control plane up :" + listenPort);
                notifyOp(callback, true, null);
            } catch (Exception e) {
                authToken = "";
                listenPort = 0;
                running = false;
                Log.w(TAG, "start failed: " + e.getMessage());
                notifyOp(callback, false, e.getMessage());
            }
        }
    }

    private void stopOnWorker() {
        synchronized (sessionLock) {
            if (httpServer != null) {
                httpServer.stop();
            }
            running = false;
            listenPort = 0;
            authToken = "";
        }
    }

    private void ensureWorker() {
        if (worker != null) {
            return;
        }
        workerThread = new HandlerThread("ra-control-worker");
        workerThread.start();
        worker = new Handler(workerThread.getLooper());
    }

    private static void notifyOp(IVpnOperationCallback callback, boolean ok, String reason) {
        if (callback == null) {
            return;
        }
        try {
            if (ok) {
                callback.onSuccess();
            } else {
                callback.onFailure(reason != null ? reason : "error");
            }
        } catch (RemoteException e) {
            Log.w(TAG, "operation callback died: " + e.getMessage());
        }
    }

    private final class HostBridgeImpl implements RemoteAccessControlHttpServer.HostBridge {
        @Override
        public String getSettingsJson() {
            IRemoteAccessControlHost h = host;
            if (h == null) {
                return "{\"ok\":false,\"error\":\"host not bound\"}";
            }
            try {
                return h.getSettingsJson();
            } catch (RemoteException e) {
                return "{\"ok\":false,\"error\":\"host unreachable\"}";
            }
        }

        @Override
        public String applySettingsJson(String body) {
            IRemoteAccessControlHost h = host;
            if (h == null) {
                return "{\"ok\":false,\"error\":\"host not bound\"}";
            }
            try {
                return h.applySettingsJson(body);
            } catch (RemoteException e) {
                return "{\"ok\":false,\"error\":\"host unreachable\"}";
            }
        }

        @Override
        public String getInternalsJson() {
            IRemoteAccessControlHost h = host;
            if (h == null) {
                return "{\"ok\":false,\"error\":\"host not bound\"}";
            }
            try {
                return h.getInternalsJson();
            } catch (RemoteException e) {
                return "{\"ok\":false,\"error\":\"host unreachable\"}";
            }
        }
    }
}
