package com.foxx.androidcast.vpn;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.VpnService;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.util.Log;

import androidx.core.app.NotificationCompat;

import com.foxx.androidcast.DeveloperSettingsActivity;
import com.foxx.androidcast.R;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/** TUN fallback when GoBackend cannot start — runs in :vpn process only. */
public final class RemoteAccessVpnService extends VpnService {
    private static final String TAG = "RemoteAccessVPN";
    public static final String ACTION_UP = "com.foxx.androidcast.vpn.VPN_UP";
    public static final String ACTION_DOWN = "com.foxx.androidcast.vpn.VPN_DOWN";
    public static final String EXTRA_WG_CONFIG = "wg_config";

    private static final int NOTIF_ID = 0x7a01;
    private static final String CHANNEL_ID = "remote_access_vpn";

    private ParcelFileDescriptor tun;

    public static boolean startWithConfig(Context context, String wgConfig) {
        Intent prep = VpnService.prepare(context);
        if (prep != null) {
            Log.w(TAG, "VPN permission not granted");
            return false;
        }
        Intent i = new Intent(context, RemoteAccessVpnService.class);
        i.setAction(ACTION_UP);
        i.putExtra(EXTRA_WG_CONFIG, wgConfig);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(i);
        } else {
            context.startService(i);
        }
        return true;
    }

    public static void stop(Context context) {
        Intent i = new Intent(context, RemoteAccessVpnService.class);
        i.setAction(ACTION_DOWN);
        context.startService(i);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        String action = intent != null ? intent.getAction() : null;
        if (ACTION_DOWN.equals(action)) {
            tearDown();
            stopForeground(true);
            stopSelf();
            return START_NOT_STICKY;
        }
        if (ACTION_UP.equals(action)) {
            String cfg = intent.getStringExtra(EXTRA_WG_CONFIG);
            ensureChannel();
            startForeground(NOTIF_ID, buildNotification("WireGuard remote access"));
            establishTun(cfg);
            return START_STICKY;
        }
        return START_NOT_STICKY;
    }

    private void establishTun(String wgConfig) {
        tearDown();
        try {
            String address = parseAddress(wgConfig);
            Builder b = new Builder();
            b.setSession("AndroidCast RA");
            if (address != null) {
                String[] parts = address.split("/");
                b.addAddress(InetAddress.getByName(parts[0]),
                        parts.length > 1 ? Integer.parseInt(parts[1]) : 32);
            }
            for (String route : parseAllowedRoutes(wgConfig)) {
                String[] rp = route.split("/");
                if (rp.length >= 2) {
                    b.addRoute(rp[0], Integer.parseInt(rp[1]));
                }
            }
            b.setMtu(1280);
            tun = b.establish();
            Log.i(TAG, "VPN interface established");
        } catch (Exception e) {
            Log.e(TAG, "VPN establish failed", e);
        }
    }

    private static String parseAddress(String wgConfig) {
        if (wgConfig == null) {
            return null;
        }
        Matcher m = Pattern.compile("(?m)^Address\\s*=\\s*(.+)$").matcher(wgConfig);
        return m.find() ? m.group(1).trim() : null;
    }

    private static String[] parseAllowedRoutes(String wgConfig) {
        if (wgConfig == null) {
            return new String[0];
        }
        Matcher m = Pattern.compile("(?m)^AllowedIPs\\s*=\\s*(.+)$").matcher(wgConfig);
        if (!m.find()) {
            return new String[0];
        }
        String[] parts = m.group(1).trim().split("\\s*,\\s*");
        ArrayList<String> out = new ArrayList<>();
        for (String p : parts) {
            if (!p.isEmpty()) {
                out.add(p.trim());
            }
        }
        return out.toArray(new String[0]);
    }

    private void tearDown() {
        if (tun != null) {
            try {
                tun.close();
            } catch (Exception ignored) {
            }
            tun = null;
        }
    }

    private Notification buildNotification(String text) {
        Intent open = new Intent(this, DeveloperSettingsActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, open,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
        return new NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_notification)
                .setContentTitle(getString(R.string.dev_remote_access_notification_title))
                .setContentText(text)
                .setContentIntent(pi)
                .setOngoing(true)
                .build();
    }

    private void ensureChannel() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            return;
        }
        NotificationManager nm = getSystemService(NotificationManager.class);
        if (nm == null) {
            return;
        }
        NotificationChannel ch = new NotificationChannel(CHANNEL_ID,
                getString(R.string.dev_remote_access_notification_channel),
                NotificationManager.IMPORTANCE_LOW);
        nm.createNotificationChannel(ch);
    }

    @Override
    public void onDestroy() {
        tearDown();
        super.onDestroy();
    }
}
