#!/usr/bin/env perl

use strict;
use warnings;
use Net::Ping;
use POSIX qw(strftime);

# --- Configuration ---

# How many seconds to wait between checks.
# 600 seconds = 10 minutes.
my $check_interval = 600;

# The number of consecutive failed checks required before we take action.
# This makes the script more robust against temporary network glitches.
my $consecutive_failures_needed = 2;

# A reliable IP address to check for basic connectivity.
my $check_host_ip = '8.8.8.8';

# A reliable domain to check. This also verifies that DNS is working.
my $check_host_domain = 'google.com';

# How many seconds to wait for a ping response.
my $ping_timeout = 5;

# How long to wait after restarting NetworkManager before checking again.
my $wait_after_restart = 60;

# --- End of Configuration ---


$| = 1; # Set autoflush on STDOUT to see logs immediately.
my $failure_count = 0;

log_message("INFO", "Starting Robust WiFi connection monitor. Will check every " . ($check_interval / 60) . " minutes.");
log_message("INFO", "Will restart NetworkManager after $consecutive_failures_needed consecutive failed checks.");
log_message("INFO", "This script needs to be run with 'sudo' or as root to restart NetworkManager.");


# Main monitoring loop
while (1) {
    if ( is_connected() ) {
        if ($failure_count > 0) {
            log_message("INFO", "Connection has been restored.");
        }
        $failure_count = 0; # Reset counter on success
    }
    else {
        $failure_count++;
        log_message("WARN", "Connection test failed. Consecutive failures: $failure_count of $consecutive_failures_needed.");
    }

    if ($failure_count >= $consecutive_failures_needed) {
        log_message("ERROR", "Connection lost. Threshold reached. Attempting to restart NetworkManager...");
        
        restart_network_manager();
        
        $failure_count = 0; # Reset counter after taking action
        
        log_message("INFO", "Waiting for $wait_after_restart seconds for network to stabilize...");
        sleep $wait_after_restart;
    }
    
    log_message("DEBUG", "Waiting for " . ($check_interval / 60) . " minutes until the next check...");
    sleep $check_interval;
}


### Subroutines ###

sub is_connected {
    log_message("DEBUG", "Pinging IP $check_host_ip and domain $check_host_domain...");
    my $p = Net::Ping->new("icmp", $ping_timeout);
    # Connection is only "up" if both basic IP and DNS resolution work.
    if ( $p->ping($check_host_ip) && $p->ping($check_host_domain) ) {
        $p->close();
        return 1; # Success
    }
    $p->close();
    return 0; # Failure
}

sub restart_network_manager {
    my $exit_code = system("systemctl", "restart", "NetworkManager.service");
    
    if ($exit_code == 0) {
        log_message("INFO", "Successfully executed 'systemctl restart NetworkManager'.");
    } else {
        my $real_exit = $exit_code >> 8;
        log_message("ERROR", "Failed to restart NetworkManager! Command exited with status: $real_exit");
        log_message("ERROR", "Please ensure you are running this script with sufficient privileges (e.g., as root).");
    }
}

sub log_message {
    my ($level, $message) = @_;
    my $timestamp = strftime('%Y-%m-%d %H:%M:%S', localtime);
    print "[$timestamp] [$level] $message\n";
}
