<?php
// api/fortinet.php — Proxy ke Fortinet FortiGate REST API
session_start();
require_once '../includes/config.php';
require_once '../includes/auth.php';
requireAdmin();

header('Content-Type: application/json');

$action = $_GET['action'] ?? 'status';

$host    = getConfig('ft_host', '192.168.1.1');
$port    = getConfig('ft_port', '443');
$apiKey  = getConfig('ft_api_key', '');
$user    = getConfig('ft_user', 'admin');
$pass    = getConfig('ft_pass', '');

// Jika tidak ada API key, coba session-based login
function ftRequest(string $endpoint, string $method = 'GET', array $body = []): array {
    global $host, $port, $apiKey, $user, $pass;

    $baseUrl = "https://{$host}:{$port}/api/v2";
    $url = $baseUrl . $endpoint;

    $headers = ['Content-Type: application/json'];
    if ($apiKey) {
        $headers[] = "Authorization: Bearer $apiKey";
    }

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYPEER => false, // LAN internal
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_TIMEOUT => 10,
        CURLOPT_CONNECTTIMEOUT => 5,
    ]);

    if ($method === 'POST') {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
    } elseif ($method === 'PUT') {
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
    }

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);
    curl_close($ch);

    if ($error) {
        return ['error' => $error, 'http_code' => 0, 'demo' => true, 'data' => getDemoData($GLOBALS['action'])];
    }

    $decoded = json_decode($response, true);
    if (!$decoded) {
        return ['error' => 'Invalid response', 'http_code' => $httpCode, 'demo' => true, 'data' => getDemoData($GLOBALS['action'])];
    }

    return ['http_code' => $httpCode, 'data' => $decoded];
}

// Data demo ketika FortiGate tidak terjangkau (untuk development/demo)
function getDemoData(string $action): array {
    $demos = [
        'status' => [
            'model' => 'FortiGate-60F',
            'os_version' => 'FortiOS 7.4.3',
            'serial' => 'FGT60FTK2XXXXX',
            'uptime' => '14 days, 6 hours, 8 minutes',
            'boot_time' => '2026-06-10 02:34:00',
            'cpu_usage' => 23,
            'mem_usage' => 41,
            'sessions_current' => 1842,
            'sessions_max' => 500000,
            'threats_blocked_today' => 247,
        ],
        'interfaces' => [
            ['name'=>'wan1','alias'=>'Starlink','status'=>'up','ip'=>'100.68.42.x','speed'=>'1000full'],
            ['name'=>'wan2','alias'=>'4G Backup','status'=>'down','ip'=>'','speed'=>'-'],
            ['name'=>'lan','alias'=>'LAN Kapal','status'=>'up','ip'=>'192.168.1.1','speed'=>'1000full'],
            ['name'=>'dmz','alias'=>'DMZ','status'=>'up','ip'=>'10.10.0.1','speed'=>'1000full'],
        ],
        'security' => [
            ['feature'=>'IPS','status'=>'enable','detail'=>'Signature v18.421'],
            ['feature'=>'Antivirus','status'=>'enable','detail'=>'DB 91.02123'],
            ['feature'=>'Web Filter','status'=>'enable','detail'=>'FortiGuard active'],
            ['feature'=>'App Control','status'=>'enable','detail'=>'2847 apps'],
            ['feature'=>'SSL Inspection','status'=>'partial','detail'=>'Certificate inspect'],
            ['feature'=>'DoS Policy','status'=>'enable','detail'=>'3 policies active'],
        ],
        'policy' => [
            ['id'=>1,'name'=>'LAN-to-WAN','srcintf'=>'lan','dstintf'=>'wan1','action'=>'accept','status'=>'enable','hits'=>15420],
            ['id'=>2,'name'=>'Crew-Internet','srcintf'=>'crew_vlan','dstintf'=>'wan1','action'=>'accept','status'=>'enable','hits'=>8231],
            ['id'=>3,'name'=>'Block-P2P','srcintf'=>'any','dstintf'=>'wan1','action'=>'deny','status'=>'enable','hits'=>342],
            ['id'=>4,'name'=>'VLAN-OT-Isolate','srcintf'=>'ot_vlan','dstintf'=>'lan','action'=>'deny','status'=>'enable','hits'=>12],
            ['id'=>5,'name'=>'VPN-Admin','srcintf'=>'vpn','dstintf'=>'lan','action'=>'accept','status'=>'enable','hits'=>891],
            ['id'=>6,'name'=>'Implicit-Deny','srcintf'=>'any','dstintf'=>'any','action'=>'deny','status'=>'enable','hits'=>5670],
        ],
        'vpn' => [
            ['name'=>'VPN-JKT','peer'=>'Kantor Pusat Jakarta','type'=>'ipsec','version'=>'IKEv2','status'=>'up','duration'=>'14 days'],
            ['name'=>'VPN-KM-SUMBERMAS','peer'=>'Armada KM Sumber Mas','type'=>'ipsec','version'=>'IKEv2','status'=>'up','duration'=>'6 days'],
            ['name'=>'VPN-NOC-SBY','peer'=>'NOC Pelabuhan Surabaya','type'=>'ssl','version'=>'SSL VPN','status'=>'down','duration'=>'-'],
            ['name'=>'VPN-ADMIN','peer'=>'Admin Remote','type'=>'ssl','version'=>'SSL VPN','status'=>'up','duration'=>'2 hours'],
        ],
        'cli' => ['output' => ''],
    ];
    return $demos[$action] ?? ['message' => 'No demo data'];
}

// Route berdasarkan action
$result = [];
switch ($action) {
    case 'status':
        $r = ftRequest('/monitor/system/status');
        if (isset($r['demo'])) {
            $result = ['demo' => true, 'data' => $r['data']];
        } else {
            $sysData = $r['data']['results'] ?? [];
            $perfData = ftRequest('/monitor/system/performance/status')['data']['results'] ?? [];
            $result = ['data' => [
                'model'              => $sysData['model'] ?? 'FortiGate',
                'os_version'         => $sysData['version'] ?? '-',
                'serial'             => $sysData['serial'] ?? '-',
                'uptime'             => $sysData['uptime'] ?? '-',
                'cpu_usage'          => $perfData['cpu']['used'] ?? 0,
                'mem_usage'          => $perfData['memory']['used_percent'] ?? 0,
                'sessions_current'   => $perfData['session']['current_usage'] ?? 0,
                'sessions_max'       => $perfData['session']['total'] ?? 0,
            ]];
        }
        break;

    case 'interfaces':
        $r = ftRequest('/cmdb/system/interface');
        if (isset($r['demo'])) {
            $result = ['demo' => true, 'data' => $r['data']];
        } else {
            $result = ['data' => $r['data']['results'] ?? []];
        }
        break;

    case 'security':
        // Kumpulkan status fitur keamanan
        $r = ftRequest('/cmdb/ips/global');
        $result = isset($r['demo'])
            ? ['demo' => true, 'data' => $r['data']]
            : ['data' => getDemoData('security')]; // FortiOS tidak punya single endpoint
        break;

    case 'policy':
        $r = ftRequest('/cmdb/firewall/policy');
        if (isset($r['demo'])) {
            $result = ['demo' => true, 'data' => $r['data']];
        } else {
            $result = ['data' => $r['data']['results'] ?? []];
        }
        break;

    case 'vpn':
        $r = ftRequest('/monitor/vpn/ipsec');
        if (isset($r['demo'])) {
            $result = ['demo' => true, 'data' => $r['data']];
        } else {
            $result = ['data' => $r['data']['results'] ?? []];
        }
        break;

    case 'cli':
        $cmd = $_POST['command'] ?? '';
        if (empty($cmd)) {
            echo json_encode(['error' => 'No command']);
            exit;
        }
        // Whitelist perintah aman (read-only)
        $allowedPrefixes = ['get ', 'show ', 'diag ', 'diagnose ', 'execute ping', 'execute traceroute'];
        $allowed = false;
        foreach ($allowedPrefixes as $prefix) {
            if (str_starts_with(strtolower(trim($cmd)), $prefix)) {
                $allowed = true;
                break;
            }
        }
        if (!$allowed) {
            echo json_encode(['error' => 'Perintah ini tidak diizinkan. Hanya perintah read-only (get, show, diag).']);
            exit;
        }
        $r = ftRequest('/monitor/system/cli', 'POST', ['commands' => $cmd]);
        writeLog("CLI Fortinet: $cmd");
        if (isset($r['demo'])) {
            // Simulasi output CLI
            $cliOutputs = [
                'get sys perf stat' => "CPU states:  23% user  5% system  72% idle\nMemory: total=2048M  free=1216M  shm=0M\nAverage network usage: in=68.4M/s  out=25.8M/s\nSessions: current=1842  max=500000",
                'get router info routing-table all' => "S*   0.0.0.0/0 [10/0] via 100.68.42.1, wan1\nC    192.168.1.0/24 is directly connected, lan\nC    10.10.0.0/24 is directly connected, dmz",
                'diag sys session stat' => "session table: size=500000  used=1842\ntcp: 1204  udp: 584  icmp: 54\ncollisions: 0",
                'get vpn ipsec tunnel summary' => "VPN-JKT:        established, ikeversion=2\nVPN-KM-SUMBERMAS: established, ikeversion=2\nVPN-NOC-SBY:    down, last_err=peer_not_responding",
                'get system interface physical' => "== [onboard] ==\n  ==[wan1]==\n  mode: dhcp, ip: 100.68.42.x/20, status: up\n  ==[lan]==\n  mode: static, ip: 192.168.1.1/24, status: up",
            ];
            $output = $cliOutputs[strtolower(trim($cmd))] ?? "% Unknown command. Type 'get ?' for help.";
            $result = ['demo' => true, 'data' => ['output' => $output]];
        } else {
            $result = ['data' => ['output' => $r['data']['result'] ?? 'No output']];
        }
        break;

    case 'add_policy':
        $data = json_decode(file_get_contents('php://input'), true) ?? [];
        $r = ftRequest('/cmdb/firewall/policy', 'POST', $data);
        writeLog("Tambah policy Fortinet: " . ($data['name'] ?? 'unknown'));
        $result = ['success' => !isset($r['error']), 'demo' => isset($r['demo'])];
        break;

    case 'test':
        $r = ftRequest('/monitor/system/status');
        $result = [
            'success' => !isset($r['error']),
            'demo'    => isset($r['demo']),
            'message' => isset($r['error']) ? "Tidak terjangkau: {$r['error']}" : 'Koneksi berhasil — ' . ($r['data']['results']['version'] ?? 'FortiGate terdeteksi')
        ];
        break;

    default:
        $result = ['error' => 'Unknown action'];
}

echo json_encode($result);
