#!/usr/bin/perl
# ==============================================================================
#  PressOps "Ignite" Installer (v1.0 - Release Candidate 2)
#  (c) 2025 LGEM Labs (lgemlabs.com)
#
#  Features:
#  - Stack: Apache/Nginx + PHP-FPM (Event Mode) + MariaDB
#  - Security: Fortified phpMyAdmin, Auto-SSL, Firewall
#  - Core: Full OS Alignment, Auto-Detect Trixie/Bookworm
#  - UI: Full Dashboard & Interactive Menus
# ==============================================================================

use strict;
use warnings;
use Getopt::Long;
use File::Path qw(make_path remove_tree);

# --- GLOBAL CONFIG ---
my $APP_DIR     = "/opt/pressops";
my $WEB_ROOT    = "$APP_DIR/webroot";
my $STATE_FILE  = "$APP_DIR/.pressops_state";
my $PMA_DIR     = "$APP_DIR/pma";

# --- CLI ARGUMENTS ---
my $cli_create  = 0;
my $cli_domain  = "";
my $cli_php     = "";
my $cli_web     = "";

GetOptions(
    "create"      => \$cli_create,
    "domain=s"    => \$cli_domain,
    "php=s"       => \$cli_php,
    "webserver=s" => \$cli_web,
);

# --- BOOTSTRAP ---
check_root();
check_os_compatibility();
initialize_repos(); 

if ($cli_create) {
    if (!$cli_php) { $cli_php = get_latest_php_version(); }
    my $target_web = $cli_web || "nginx"; 
    handle_webserver_conflict_headless($target_web);
    install_stack($cli_domain, $cli_php, $target_web, "none", [], "admin\@example.com", "none"); 
    exit;
}

# Interactive Dashboard
my %system_status = scan_system_status();
show_dashboard(\%system_status);

while (1) {
    print_menu();
    my $choice = <STDIN>; chomp($choice);
    handle_choice($choice, \%system_status);
}

# ==============================================================================
#  CORE LOGIC
# ==============================================================================

sub handle_choice {
    my ($c, $s) = @_;

    if ($c eq "1") {
        if (-e $STATE_FILE) {
            print "\n[!] System is already installed. Use 'Uninstall/Cleanup' menu.\n";
            return;
        }
        
        my $dom = prompt_user("Enter Primary Domain (e.g. lgemlabs.com): ");
        $dom =~ s/^www\.//; 
        
        my $target_web = select_webserver_interactive();
        if (!$target_web) { return; } 
        
        my $php = select_php_interactive();
        my ($fw_type, $fw_ips) = select_firewall_interactive();
        my $pma_mode = select_pma_interactive(); 

        my $email = prompt_user("Enter Admin Email (for SSL & WP Admin): ");

        install_stack($dom, $php, $target_web, $fw_type, $fw_ips, $email, $pma_mode);
    }
    elsif ($c eq "2") {
        my $target_web = select_webserver_interactive();
        if ($target_web) { swap_webserver($target_web); }
    }
    elsif ($c eq "3") {
        print "\nCurrent Firewall: " . check_firewall_status() . "\n";
        my ($fw_type, $fw_ips) = select_firewall_interactive();
        configure_firewall($fw_type, $fw_ips);
    }
    elsif ($c eq "4") {
        show_ssl_submenu($s);
    }
    elsif ($c eq "5") {
        print "\n  *** DOMAIN MIGRATION WIZARD ***\n";
        my $new_dom = prompt_user("Enter New Domain (FQDN): ");
        if ($new_dom) {
            system("sudo -u pressops wp search-replace '$s->{domain}' '$new_dom' --path=$WEB_ROOT");
            print "[SUCCESS] Migrated to $new_dom.\n";
        }
    }
    elsif ($c eq "9") {
        show_uninstall_submenu($s);
    }
    elsif ($c eq "0") {
        exit;
    }
    
    %system_status = scan_system_status();
    show_dashboard(\%system_status);
}

sub initialize_repos {
    if (-e "/etc/apt/sources.list.d/php.list") { return; }
    print "[*] Initializing System Repositories...\n";
    system("apt-get update >/dev/null");
    system("apt-get -y install lsb-release apt-transport-https ca-certificates curl git unzip >/dev/null 2>&1");
    my $codename = `lsb_release -sc`; chomp($codename);
    system("curl -sSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg");
    system("echo 'deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $codename main' > /etc/apt/sources.list.d/php.list");
    print "[*] Updating package lists...\n";
    if (system("apt-get update") != 0) {
        print "\n[CRITICAL] REPO ERROR. Fallback to native?\n[1] Yes [2] Abort: ";
        my $c = <STDIN>; chomp($c);
        if ($c eq "1") { unlink("/etc/apt/sources.list.d/php.list"); system("apt-get update"); } 
        else { die "Aborted.\n"; }
    }
    print "[*] Upgrading system libraries...\n";
    system("DEBIAN_FRONTEND=noninteractive apt-get -y upgrade");
}

sub get_latest_php_version {
    my @v = `apt-cache pkgnames | grep -E '^php[0-9]+\\.[0-9]+\$' | sort -V`;
    my @c; foreach(@v){ if(/php(\d+\.\d+)/){ push(@c,$1); } }
    return $c[-1] || "8.2"; 
}

sub install_stack {
    my ($domain, $php_ver, $webserver, $firewall, $ssh_ips_ref, $email, $pma_mode) = @_;
    
    print "\n==================================================\n";
    print "  IGNITING PRESSOPS INSTALLATION\n";
    print "  Domain: www.$domain | Stack: $webserver + PHP $php_ver\n";
    print "==================================================\n";

    print "[*] Installing packages...\n";
    # [FIX] Removed 'libapache2-mod-php' to prevent legacy Prefork mode
    my @pkgs = (
        "sudo", "mariadb-server", "mariadb-client",
        "php$php_ver-fpm", "php$php_ver-mysql", "php$php_ver-xml", 
        "php$php_ver-mbstring", "php$php_ver-curl", "php$php_ver-zip", "php$php_ver-intl", 
        "php$php_ver-gd", "php$php_ver-bcmath", "certbot"
    );
    
    if ($webserver eq "nginx") {
        push(@pkgs, "nginx", "python3-certbot-nginx");
    } else {
        # Only install apache2 and certbot, NO legacy php mod
        push(@pkgs, "apache2", "python3-certbot-apache");
    }
    
    if (system("apt-get -y install " . join(" ", @pkgs)) != 0) {
        die "\n[CRITICAL ERROR] Apt-get failed.\n";
    }

    if ($webserver eq "apache") {
        # [FIX] Force Modern Event MPM + Proxy modules + Restart
        print "[*] Configuring Apache for FPM/Event mode...\n";
        system("a2dismod mpm_prefork >/dev/null 2>&1");
        system("a2dismod php$php_ver >/dev/null 2>&1"); # Just in case
        system("a2enmod mpm_event proxy_fcgi setenvif rewrite headers");
        system("systemctl restart apache2");
    }

    if ($firewall) { configure_firewall($firewall, $ssh_ips_ref); }

    print "[*] Creating structure...\n";
    make_path($WEB_ROOT);
    if (!-e "/usr/local/bin/wp") {
        system("curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar");
        system("chmod +x wp-cli.phar && mv wp-cli.phar /usr/local/bin/wp");
    }
    if (!getpwnam("pressops")) {
        system("useradd -r -d $APP_DIR -s /bin/bash pressops");
        system("chown -R pressops:www-data $APP_DIR");
    }

    my $pma_path = install_phpmyadmin($pma_mode);

    configure_vhost($domain, $webserver, $php_ver, $pma_mode, $pma_path);
    deploy_wordpress($domain, $email);
    configure_ssl_auto($domain, $webserver, $email);

    open(my $fh, '>', $STATE_FILE);
    print $fh "INSTALLED=1\nDOMAIN=$domain\nPHP=$php_ver\nWEBSERVER=$webserver\n";
    close $fh;

    print "\n[SUCCESS] PressOps Stack Fully Deployed.\n";
    if ($pma_mode eq "fortified" && $pma_path) {
        print "--------------------------------------------------\n";
        print "  DATABASE MANAGEMENT (phpMyAdmin)\n";
        print "  URL: https://www.$domain$pma_path\n";
        print "  Gate User: pma_gate\n";
        print "  Gate Pass: (The same as your WP Admin Pass)\n";
        print "--------------------------------------------------\n";
    }
    print "Admin URL: https://www.$domain/wp-admin\n";
    print "Press Enter to return to menu..."; <STDIN>;
}

# --- PMA LOGIC ---

sub select_pma_interactive {
    print "\n--------------------------------------------------\n";
    print "  Database Management (phpMyAdmin)\n";
    print "--------------------------------------------------\n";
    print "  [1] None (Best Security)\n";
    print "  [2] Localhost Only (Requires SSH Tunnel)\n";
    print "  [3] Fortified Public Access (Random URL + Password)\n";
    print "--------------------------------------------------\n";
    print "  Selection: ";
    my $s = <STDIN>; chomp($s);
    
    if ($s eq "2") { return "localhost"; }
    if ($s eq "3") { return "fortified"; }
    return "none";
}

sub install_phpmyadmin {
    my $mode = shift;
    if ($mode eq "none") { return ""; }
    
    print "[*] Installing phpMyAdmin ($mode)...\n";
    remove_tree($PMA_DIR);
    make_path($PMA_DIR);
    system("curl -sL https://www.phpmyadmin.net/downloads/phpMyAdmin-latest-english.tar.gz | tar xz -C $PMA_DIR --strip-components=1");
    
    my $secret = `openssl rand -base64 24`; chomp($secret);
    my $cfg = <<EOF;
<?php
\$cfg['blowfish_secret'] = '$secret';
\$i = 0; \$i++;
\$cfg['Servers'][\$i]['auth_type'] = 'cookie';
\$cfg['Servers'][\$i]['host'] = 'localhost';
\$cfg['Servers'][\$i]['compress'] = false;
\$cfg['Servers'][\$i]['AllowNoPassword'] = false;
\$cfg['UploadDir'] = ''; \$cfg['SaveDir'] = '';
EOF
    open(my $fh, '>', "$PMA_DIR/config.inc.php"); print $fh $cfg; close $fh;
    system("chown -R pressops:www-data $PMA_DIR");

    my $url_path = "/pma_admin"; 
    if ($mode eq "fortified") {
        my $suffix = `openssl rand -hex 4`; chomp($suffix);
        $url_path = "/db_$suffix";
    }
    return $url_path; 
}

sub configure_vhost {
    my ($domain, $webserver, $php_ver, $pma_mode, $pma_path) = @_;
    print "[*] Generating $webserver configuration...\n";

    my $pma_block = "";
    
    if ($webserver eq "nginx") {
        my $auth_directive = "";
        my $allow_directive = "deny all;"; 

        if ($pma_mode eq "localhost") {
            $allow_directive = "allow 127.0.0.1; deny all;";
        }
        elsif ($pma_mode eq "fortified") {
            $allow_directive = ""; 
            $auth_directive = <<EOF;
        auth_basic "Restricted Database Access";
        auth_basic_user_file $APP_DIR/.htpasswd;
EOF
        }

        if ($pma_mode ne "none") {
            $pma_block = <<EOF;
    location $pma_path {
        alias $PMA_DIR;
        index index.php;
        $auth_directive
        $allow_directive

        location ~ \\.php\$ {
            include snippets/fastcgi-php.conf;
            fastcgi_param SCRIPT_FILENAME \$request_filename;
            fastcgi_pass unix:/run/php/php$php_ver-fpm.sock;
        }
    }
EOF
        }
        
        my $conf = <<EOF;
server {
    listen 80;
    server_name www.$domain $domain;
    root $WEB_ROOT;
    index index.php index.html;
    location / { try_files \$uri \$uri/ /index.php?\$args; }
    location ~ \\.php\$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php$php_ver-fpm.sock;
    }
    $pma_block
    location ~ /\\.ht { deny all; }
}
EOF
        open(my $fh, '>', "/etc/nginx/sites-available/$domain"); print $fh $conf; close $fh;
        system("ln -sf /etc/nginx/sites-available/$domain /etc/nginx/sites-enabled/");
        system("rm -f /etc/nginx/sites-enabled/default");
        system("systemctl reload nginx");
        
    } else { 
        # Apache Logic
        if ($pma_mode ne "none") {
            my $alias_cmd = "Alias $pma_path $PMA_DIR";
            my $auth_cmd = "Require local"; # Default for localhost
            
            if ($pma_mode eq "fortified") {
                $auth_cmd = <<EOF;
        AuthType Basic
        AuthName "Restricted Database Access"
        AuthUserFile $APP_DIR/.htpasswd
        Require valid-user
EOF
            }
            
            $pma_block = <<EOF;
    $alias_cmd
    <Directory $PMA_DIR>
        Options FollowSymLinks
        DirectoryIndex index.php
        AllowOverride All
        $auth_cmd
        <FilesMatch \\.php\$>
            SetHandler "proxy:unix:/run/php/php$php_ver-fpm.sock|fcgi://localhost"
        </FilesMatch>
    </Directory>
EOF
        }
    
        my $conf = <<EOF;
<VirtualHost *:80>
    ServerName www.$domain
    ServerAlias $domain
    DocumentRoot $WEB_ROOT
    <Directory $WEB_ROOT>
        AllowOverride All
        Require all granted
    </Directory>
    <FilesMatch \\.php\$>
        SetHandler "proxy:unix:/run/php/php$php_ver-fpm.sock|fcgi://localhost"
    </FilesMatch>
    $pma_block
</VirtualHost>
EOF
        open(my $fh, '>', "/etc/apache2/sites-available/$domain.conf"); print $fh $conf; close $fh;
        system("a2ensite $domain.conf");
        system("a2dissite 000-default.conf");
        # [FIX] Added 'headers' here too for good measure
        system("a2enmod rewrite proxy_fcgi setenvif headers");
        system("systemctl restart apache2"); # RESTART, not reload
    }
}

sub deploy_wordpress {
    my ($domain, $email) = @_;
    print "[*] Downloading & Installing WordPress...\n";
    
    system("sudo -u pressops wp core download --path=$WEB_ROOT");
    
    my $db_pass = `openssl rand -base64 12`; chomp($db_pass);
    my $db_name = "pressops_db";
    my $db_user = "pressops_user";
    
    system("mysql -e \"CREATE DATABASE IF NOT EXISTS $db_name;\"");
    system("mysql -e \"GRANT ALL PRIVILEGES ON $db_name.* TO '$db_user'\@'localhost' IDENTIFIED BY '$db_pass';\"");
    system("mysql -e \"FLUSH PRIVILEGES;\"");
    
    system("sudo -u pressops wp config create --dbname=$db_name --dbuser=$db_user --dbpass='$db_pass' --path=$WEB_ROOT");
    
    my $admin_user = "admin";
    my $admin_pass = `openssl rand -base64 12`; chomp($admin_pass);
    
    print "[*] Running WP Install...\n";
    system("sudo -u pressops wp core install --url='https://www.$domain' --title='New PressOps Site' --admin_user='$admin_user' --admin_password='$admin_pass' --admin_email='$email' --path=$WEB_ROOT");
    
    # SYNC PASSWORDS: Create .htpasswd using OpenSSL
    if (-d $PMA_DIR) {
        my $crypt = `openssl passwd -5 '$admin_pass'`; chomp($crypt);
        open(my $fh, '>', "$APP_DIR/.htpasswd");
        print $fh "pma_gate:$crypt\n";
        close $fh;
    }
    
    print "\n--------------------------------------------------\n";
    print "  CREDENTIALS (WP Admin)\n";
    print "  User: $admin_user\n";
    print "  Pass: $admin_pass\n";
    print "--------------------------------------------------\n";
}

sub configure_ssl_auto {
    my ($domain, $webserver, $email) = @_;
    print "[*] Requesting SSL Certificate...\n";
    my $cmd = ($webserver eq "nginx") 
        ? "certbot --nginx -d $domain -d www.$domain --non-interactive --agree-tos -m $email"
        : "certbot --apache -d $domain -d www.$domain --non-interactive --agree-tos -m $email";
    
    while(1) {
        if (system($cmd) == 0) { print "[SUCCESS] SSL Installed.\n"; last; }
        print "\n[!] SSL Failed. [r]etry or [s]kip: ";
        my $c = <STDIN>; chomp($c); if (lc($c) eq "s") { last; }
    }
}

# --- RESTORED PRETTY UI SUBS ---

sub show_dashboard {
    my $s = shift;
    system("clear");
    print "========================================================\n";
    print "  PressOps Control Deck (lgemlabs.com)\n";
    print "========================================================\n";
    print "  STATUS:\n";
    print "  [*] Web Engine:    $s->{webserver}\n";
    print "  [*] PHP Version:   $s->{php}\n";
    print "  [*] Domain:        " . ($s->{domain} || "Not Configured") . "\n";
    print "========================================================\n";
}

sub print_menu {
    print "\n  AVAILABLE OPERATIONS:\n";
    print "  [1] INSTALL / REPAIR\n";
    print "  ------------------------------------------------\n";
    print "  [2] SWAP ARCH: Webserver (Nginx <-> Apache)\n";
    print "  [3] SWAP ARCH: Firewall (UFW / NFTables / None)\n";
    print "  [4] CERTIFICATE: Manage SSL\n";
    print "  ------------------------------------------------\n";
    print "  [5] REBRAND: Change Primary Domain\n";
    print "  ------------------------------------------------\n";
    print "  [9] UNINSTALL / CLEANUP (Reset Options)\n";
    print "  [0] Exit\n";
    print "\n  Select Command: ";
}

sub select_webserver_interactive {
    my $current_ws = "None";
    if (get_service_state("apache2") eq "running") { $current_ws = "apache"; }
    elsif (get_service_state("nginx") eq "running") { $current_ws = "nginx"; }
    
    print "\n--------------------------------------------------\n";
    print "  Select Web Server Architecture\n";
    print "--------------------------------------------------\n";
    my $lbl_apache = ($current_ws eq "apache") ? "Apache (Active)" : "Apache";
    my $lbl_nginx  = ($current_ws eq "nginx")  ? "Nginx  (Active)" : "Nginx";
    print "  [1] $lbl_apache\n";
    print "  [2] $lbl_nginx\n";
    print "--------------------------------------------------\n";
    print "  Selection: ";
    
    my $sel = <STDIN>; chomp($sel);
    my $target = ($sel eq "1") ? "apache" : "nginx";
    
    if ($target eq $current_ws) {
        print "\n[*] Keeping $lbl_apache active. Installing as VHost.\n";
        return $target;
    }
    
    if ($current_ws ne "None" && $target ne $current_ws && $target ne "None") {
        print "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
        print "  WARNING: ARCHITECTURE SWITCH\n";
        print "  Switching from $current_ws to $target.\n";
        print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
        print "  Proceed? (y/n): ";
        my $conf = <STDIN>; chomp($conf);
        if (lc($conf) ne "y") { return 0; }
        
        print "[*] Disabling $current_ws...\n";
        my $svc = ($current_ws eq "apache") ? "apache2" : "nginx";
        system("systemctl stop $svc");
        system("systemctl disable $svc");
    }
    return $target;
}

sub select_firewall_interactive {
    print "\n--------------------------------------------------\n";
    print "  Select Firewall Strategy\n";
    print "--------------------------------------------------\n";
    print "  [1] UFW (Simple)\n";
    print "  [2] NFTables (Pro/Atomic)\n";
    print "  [3] None (Do NOT touch firewall settings)\n";
    print "--------------------------------------------------\n";
    print "  Selection: ";
    my $sel = <STDIN>; chomp($sel);
    
    if ($sel eq "3") { return ("none", []); }
    my $type = ($sel eq "1") ? "ufw" : "nftables";
    
    print "\n  [SSH Access Control]\n";
    print "  [1] Open to World (Any IP)\n";
    print "  [2] Restrict to Specific IPs / Networks\n";
    print "  Selection: ";
    my $acc = <STDIN>; chomp($acc);
    
    my @ips = ();
    if ($acc eq "2") {
        print "\n  Enter permitted IPs (comma separated): ";
        my $input = <STDIN>; chomp($input);
        @ips = split(/[\s,]+/, $input);
    }
    return ($type, \@ips);
}

sub configure_firewall {
    my ($mode, $ips_ref) = @_;
    my @ips = @{$ips_ref};
    if ($mode eq "none") { return; }
    
    my $ssh_port = `netstat -tlpn | grep sshd | awk '{print \$4}' | awk -F: '{print \$NF}' | head -n 1`; chomp($ssh_port); $ssh_port ||= 22;
    
    if ($mode eq "ufw") {
        system("apt-get install -y ufw");
        system("ufw default deny incoming"); system("ufw allow outgoing");
        if (@ips) { foreach (@ips) { system("ufw allow from $_ to any port $ssh_port proto tcp"); } }
        else { system("ufw allow $ssh_port/tcp"); }
        system("ufw allow 80/tcp"); system("ufw allow 443/tcp");
        system("echo 'y' | ufw enable");
    } elsif ($mode eq "nftables") {
        system("apt-get install -y nftables");
        my $ssh_rule = (@ips) ? "ip saddr { " . join(", ", @ips) . " } tcp dport $ssh_port accept" : "tcp dport $ssh_port accept";
        open(my $fh, '>', "/etc/nftables.conf");
        print $fh "#!/usr/sbin/nft -f\nflush ruleset\ntable inet filter {\nchain input {\ntype filter hook input priority 0; policy drop;\niifname \"lo\" accept\nct state established,related accept\nip protocol icmp accept\nip6 nexthdr icmpv6 accept\n$ssh_rule\ntcp dport 80 accept\ntcp dport 443 accept\n}\nchain forward { type filter hook forward priority 0; policy drop; }\nchain output { type filter hook output priority 0; policy accept; }\n}\n";
        close $fh;
        system("systemctl enable nftables && systemctl restart nftables");
    }
}

sub show_ssl_submenu {
    print "  (Use Install/Repair to set SSL)\n"; <STDIN>;
}

sub show_uninstall_submenu {
    my $s = shift;
    system("clear");
    print "========================================================\n";
    print "  CLEANUP / UNINSTALL OPERATIONS\n";
    print "========================================================\n";
    print "  [1] Remove Site & Configs Only (Safe)\n";
    print "  [2] Reset Firewall Only\n";
    print "  [3] TOTAL UNINSTALL (The Hammer)\n";
    print "--------------------------------------------------------\n";
    print "  [0] Back\n";
    print "  Select: ";
    
    my $c = <STDIN>; chomp($c);
    if ($c eq "1") {
        remove_tree($WEB_ROOT); remove_tree($PMA_DIR); system("mysql -e \"DROP DATABASE IF EXISTS pressops_db;\""); unlink($STATE_FILE);
        print "Cleaned.\n"; sleep(1);
    }
    elsif ($c eq "2") {
        if (`systemctl is-active ufw` =~ /active/) { system("ufw disable"); system("ufw reset"); }
        if (`systemctl is-active nftables` =~ /active/) { system("nft flush ruleset"); }
    }
    elsif ($c eq "3") {
        system("systemctl stop nginx apache2 mariadb php*-fpm");
        system("apt-get purge -y nginx* apache2* php* mariadb-server*");
        remove_tree($APP_DIR); unlink($STATE_FILE);
    }
}

sub scan_system_status {
    my %s;
    $s{webserver} = "None";
    my $ngx = get_service_state("nginx");
    my $apc = get_service_state("apache2");
    
    if ($ngx eq "running") { $s{webserver} = "Nginx"; }
    elsif ($apc eq "running") { $s{webserver} = "Apache"; }
    elsif ($ngx ne "missing") { $s{webserver} = "Nginx (Stopped)"; }
    elsif ($apc ne "missing") { $s{webserver} = "Apache (Stopped)"; }

    $s{php} = `php -r 'echo PHP_VERSION;' 2>/dev/null` || "Not Found"; chomp($s{php});
    $s{ssl} = "Unknown";
    if (-e "/etc/letsencrypt/live") { $s{ssl} = "Let's Encrypt"; }
    if (-e $STATE_FILE) { open(my $fh, '<', $STATE_FILE); while(<$fh>){ if(/^DOMAIN=(.*)/){$s{domain}=$1} } }
    return %s;
}

sub check_root { if ($> != 0) { die "[Error] Must run as root.\n"; } }
sub prompt_user { print $_[0]; my $v=<STDIN>; chomp($v); return $v; }
sub check_firewall_status { 
    if (`systemctl is-active ufw 2>/dev/null` =~ /active/) { return "UFW (Active)"; }
    if (`systemctl is-active nftables 2>/dev/null` =~ /active/) { return "NFTables (Active)"; }
    return "None / Unknown";
}
sub get_service_state {
    my $s=shift; my $a=`systemctl is-active $s 2>/dev/null`; chomp($a);
    return ($a eq "active") ? "running" : "missing";
}
sub handle_webserver_conflict_headless {} 
sub swap_webserver {} 
sub check_os_compatibility {
    open(my $fh, '<', '/etc/os-release');
    while(<$fh>){ if(/^VERSION_ID="?([^"]+)"?/){ if($1 !~ /^(12|13)/){ 
        print "\n[!] Warning: Non-Debian 12/13 detected. Proceeding anyway.\n";
    }}}
}

sub select_php_interactive {
    print "\n[*] Finding PHP versions...\n";
    my @v = `apt-cache pkgnames | grep -E '^php[0-9]+\\.[0-9]+\$' | sort -V`;
    my @c; foreach(@v){ if(/php(\d+\.\d+)/){ push(@c,$1); } }
    my %s; @c = grep{!$s{$_}++} @c; 
    
    my $l = $c[-1] || "8.2";

    print "-------------------------------------------------------\n";
    print "  Available PHP Versions:\n";
    my $i = 1;
    foreach my $ver (@c) {
        my $tag = ($ver eq $l) ? " (*)" : "";
        print "  [$i] PHP $ver $tag\n";
        $i++;
    }
    print "-------------------------------------------------------\n";
    print "  Selection [Default: $l]: ";
    my $sel = <STDIN>; chomp($sel);
    if ($sel =~ /^\d+$/ && $sel > 0 && $sel <= scalar(@c)) { 
        my $val = $c[$sel-1];
        if ($val =~ /(\d+\.\d+)/) { return $1; }
        return $val;
    }
    return $l;
}
