<?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 = 30;
$macCacheTime = 60;
$mikrotikCacheTime = 15;

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

/*
|--------------------------------------------------------------------------
| 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 MIKROTIK MAP
|--------------------------------------------------------------------------
*/
if (file_exists($cacheMikrotik) && (time() - filemtime($cacheMikrotik)) < $mikrotikCacheTime) {
    $mikrotikMap = json_decode(file_get_contents($cacheMikrotik), true);
} else {

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

    if (!empty($users)) {
        foreach ($users as $u) {
            if (!empty($u['caller-id'])) {
                $mac = formatMac($u['caller-id']);
                $mikrotikMap[$mac] = [
                    'name' => $u['name'],
                    'router_mac' => $mac
                ];
            }
        }
    }

    file_put_contents($cacheMikrotik, json_encode($mikrotikMap));
}

/*
|--------------------------------------------------------------------------
| LOAD ONU LIST
|--------------------------------------------------------------------------
*/
if (file_exists($cacheOnu) && (time() - filemtime($cacheOnu)) < $onuCacheTime) {
    $onuOutput = file_get_contents($cacheOnu);
} else {
    $onuOutput = runTelnetCommand("show epon onu-information");
    file_put_contents($cacheOnu, $onuOutput);
}

$allOnu = parseOnuList($onuOutput);

/*
|--------------------------------------------------------------------------
| LOAD FULL MAC TABLE
|--------------------------------------------------------------------------
*/
if (file_exists($cacheAllMac) && (time() - filemtime($cacheAllMac)) < $macCacheTime) {
    $macOutput = file_get_contents($cacheAllMac);
} else {
    $macOutput = runTelnetCommand("show mac address-table", 15);
    file_put_contents($cacheAllMac, $macOutput);
}

$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>