<?php
if(!isset($_SESSION['userid'])){
    exit("Unauthorized Access");
}

ini_set('max_execution_time', 300);
date_default_timezone_set('Asia/Dhaka');

/*
|--------------------------------------------------------------------------
| CONFIG
|--------------------------------------------------------------------------
*/

$oltIp = "157.10.28.198";
$port = "2323";
$username = "admin";
$password = "admin";
$enablePassword = "admin";

/*
|--------------------------------------------------------------------------
| CACHE CONFIG
|--------------------------------------------------------------------------
*/

$cacheDir = __DIR__ . '/cache';

$cacheOnu = $cacheDir . '/onu_cache.txt';
$cacheAllMac = $cacheDir . '/mac_all.txt';
$cacheMikrotik = $cacheDir . '/mikrotik_cache.json';

$onuCacheTime = 1800;
$macCacheTime = 1800;
$mikrotikCacheTime = 900;

if (!file_exists($cacheDir)) {
    mkdir($cacheDir, 0777, true);
}

/*
|--------------------------------------------------------------------------
| CACHE HELPER
|--------------------------------------------------------------------------
*/

function getCacheData($cacheFile, $ttl, $callback){

    if(file_exists($cacheFile)){
        if((time() - filemtime($cacheFile)) < $ttl){
            $data = file_get_contents($cacheFile);
            return json_decode($data, true) ?: $data;
        }
    }

    $data = $callback();

    if(is_array($data)){
        file_put_contents($cacheFile, json_encode($data));
    }else{
        file_put_contents($cacheFile, $data);
    }

    return $data;
}

/*
|--------------------------------------------------------------------------
| HELPER FUNCTIONS
|--------------------------------------------------------------------------
*/

function formatMac($mac){
    $mac = str_replace(['.', '-', ':'], '', strtolower(trim($mac)));
    return implode(':', str_split($mac, 2));
}

function runTelnetCommand($command, $timeout = 8){

    global $oltIp, $port, $username, $password, $enablePassword;

    $script = "/usr/bin/expect -c '
    set timeout $timeout
    spawn telnet $oltIp $port
    expect \"Username:\"
    send \"$username\r\"
    expect \"Password:\"
    send \"$password\r\"
    expect \">\"\"
    send \"enable\r\"
    expect \"Password:\"
    send \"$enablePassword\r\"
    expect \"#\"
    send \"$command\r\"
    expect \"#\"
    send \"exit\r\"
    expect eof
    '";

    return shell_exec($script);
}

function parseOnuList($output){

    $lines = explode("\n", $output);
    $data = [];

    foreach ($lines as $line) {

        if (preg_match('/(EPON\S+)\s+(\S+)\s+(\S+)\s+([0-9A-F\.]+)\s+.*\s+(auto-configured|deregistered)/i', $line, $m)) {

            $statusRaw = strtolower($m[5]);

            $data[] = [
                "interface" => trim($m[1]),
                "vendor"    => trim($m[2]),
                "model"     => trim($m[3]),
                "mac"       => formatMac($m[4]),
                "status"    => ($statusRaw == "auto-configured") ? "UP" : "DOWN"
            ];
        }
    }

    return $data;
}

function parseMacTable($output){

    $lines = explode("\n", $output);
    $data = [];
    $capture = false;

    foreach ($lines as $line) {

        $line = trim($line);

        if (stripos($line, 'Vlan') !== false && stripos($line, 'Mac Address') !== false) {
            $capture = true;
            continue;
        }

        if (!$capture || empty($line) || strpos($line, '----') !== false) {
            continue;
        }

        if (preg_match('/^(\d+)\s+([0-9a-f]{4}\.[0-9a-f]{4}\.[0-9a-f]{4})\s+(\w+)\s+(.+)$/i', $line, $m)) {

            $data[] = [
                'vlan' => $m[1],
                'mac'  => formatMac($m[2]),
                'type' => $m[3],
                'port' => strtolower(trim($m[4]))
            ];
        }
    }

    return $data;
}

function groupMacByInterface($macList){

    $grouped = [];

    foreach($macList as $m){
        $grouped[$m['port']][] = $m;
    }

    return $grouped;
}

/*
|--------------------------------------------------------------------------
| LOAD CACHE DATA
|--------------------------------------------------------------------------
*/

$onuOutput = getCacheData(
    $cacheOnu,
    $onuCacheTime,
    function(){
        return runTelnetCommand("show epon onu-information");
    }
);

$macOutput = getCacheData(
    $cacheAllMac,
    $macCacheTime,
    function(){
        return runTelnetCommand("show mac address-table", 15);
    }
);

$mikrotikMap = getCacheData(
    $cacheMikrotik,
    $mikrotikCacheTime,
    function() use ($obj){

        $users = $obj->pppeoActiveSecretList(1);
        $map = [];

        if(!empty($users)){
            foreach($users as $u){
                if(!empty($u['caller-id'])){

                    $mac = formatMac($u['caller-id']);

                    $map[$mac] = [
                        'name' => $u['name'],
                        'router_mac' => $mac
                    ];
                }
            }
        }

        return $map;
    }
);

$allOnu = parseOnuList($onuOutput);
$allMacList = parseMacTable($macOutput);
$macGrouped = groupMacByInterface($allMacList);

/*
|--------------------------------------------------------------------------
| PAGINATION
|--------------------------------------------------------------------------
*/

$perPage = 10;
$currentPage = isset($_GET['pg']) ? max(1, intval($_GET['pg'])) : 1;

$totalPage = ceil(count($allOnu) / $perPage);

$onus = array_slice($allOnu, ($currentPage-1)*$perPage, $perPage);
?>

<!DOCTYPE html>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>

<body class="bg-light">

<div class="container mt-4">
<h4>ONU Monitoring Dashboard</h4>

<table class="table table-bordered">
<thead class="table-dark">
<tr>
<th>Interface</th>
<th>Vendor</th>
<th>Model</th>
<th>ONU MAC</th>
<th>Status</th>
<th>Sync</th>
<th>User</th>
<th>Router MAC</th>
</tr>
</thead>

<tbody>

<?php foreach ($onus as $o):

    $interfaceKey = strtolower($o['interface']);
    $macList = $macGrouped[$interfaceKey] ?? [];

    $matchedUser = null;
    $routerMac = null;

    foreach ($macList as $m) {
        if (isset($mikrotikMap[$m['mac']])) {
            $matchedUser = $mikrotikMap[$m['mac']]['name'];
            $routerMac = $mikrotikMap[$m['mac']]['router_mac'];
            break;
        }
    }
?>

<tr>
<td><?= $o['interface'] ?></td>
<td><?= $o['vendor'] ?></td>
<td><?= $o['model'] ?></td>
<td><?= $o['mac'] ?></td>

<td>
<?= ($o['status']=="UP")
    ? "<span class='badge bg-success'>UP</span>"
    : "<span class='badge bg-danger'>DOWN</span>" ?>
</td>

<td>
<?php if ($matchedUser): ?>
<span class="badge bg-success">Matched</span>
<?php else: ?>
<span class="badge bg-warning text-dark">No Client</span>
<?php endif; ?>
</td>

<td>
<?= $matchedUser ? htmlspecialchars($matchedUser) : "<span class='text-muted'>N/A</span>" ?>
</td>

<td>
<?= $routerMac ? "<span class='badge bg-info'>$routerMac</span>" : "<span class='text-muted'>N/A</span>" ?>
</td>

</tr>

<?php endforeach; ?>

</tbody>
</table>

<?php if ($totalPage > 1): ?>
<nav>
<ul class="pagination">

<?php for ($i=1;$i<=$totalPage;$i++):
$query = $_GET;
$query['pg'] = $i;
$link = '?' . http_build_query($query);
?>

<li class="page-item <?= ($i==$currentPage)?'active':'' ?>">
<a href="<?= $link ?>" class="page-link"><?= $i ?></a>
</li>

<?php endfor; ?>

</ul>
</nav>
<?php endif; ?>

</div>
</body>
</html>