<?php

require_once __DIR__ . '/../vendor/autoload.php';

use PHPNative\Framework\Application;
use PHPNative\Framework\HetznerClient;
use PHPNative\Framework\IconFontRegistry;
use PHPNative\Framework\Profiler;
use PHPNative\Framework\Settings;
use PHPNative\Tailwind\Data\Icon as IconName;
use PHPNative\Ui\Widget\Button;
use PHPNative\Ui\Widget\Container;
use PHPNative\Ui\Widget\FileBrowser;
use PHPNative\Ui\Widget\Icon;
use PHPNative\Ui\Widget\Label;
use PHPNative\Ui\Widget\Menu;
use PHPNative\Ui\Widget\MenuBar;
use PHPNative\Ui\Widget\Modal;
use PHPNative\Ui\Widget\StatusBar;
use PHPNative\Ui\Widget\TabContainer;
use PHPNative\Ui\Widget\Table;
use PHPNative\Ui\Widget\TextInput;
use PHPNative\Ui\Window;

$iconFontCandidates = [
    __DIR__ . '/../assets/fonts/fa-solid-900.ttf',
    __DIR__ . '/../assets/fonts/fontawesome/fa7_freesolid_900.otf',
    '/usr/share/fonts/truetype/fontawesome-webfont.ttf',
    '/usr/share/fonts/truetype/fontawesome/fa-solid-900.ttf',
    '/usr/share/fonts/truetype/fa-solid-900.ttf',
];

$iconFontPath = null;
foreach ($iconFontCandidates as $candidate) {
    if (is_file($candidate)) {
        $iconFontPath = $candidate;
        break;
    }
}

if ($iconFontPath !== null) {
    IconFontRegistry::setDefaultFontPath($iconFontPath);
} else {
    echo "Hinweis: FontAwesome Font nicht gefunden. Icons werden ohne Symbol dargestellt.\n";
}

// Enable profiler to identify performance bottlenecks (disabled by default)
// Profiler::enable();

$app = new Application();
$window = new Window('Windows Application Example', 800, 600);

// Initialize settings
$settings = new Settings('WindowsAppExample');
$currentApiKey = $settings->get('api_key', '');
$currentPrivateKeyPath = $settings->get('private_key_path', '');

/** @var Label|null $statusLabel */
$statusLabel = null;

// Store selected server for SFTP connection
$selectedServer = null;

// Main container (flex-col: menu, content, status)
$mainContainer = new Container('flex flex-col bg-gray-100');

// Modal dialog setup (hidden by default)
$apiKeyInput = new TextInput('API Key', 'w-full border border-gray-300 rounded px-3 py-2 bg-white text-black');
$privateKeyPathInput = new TextInput(
    'Private Key Path',
    'w-full border border-gray-300 rounded px-3 py-2 bg-white text-black',
);

$modalDialog = new Container('bg-white rounded-lg p-6 flex flex-col w-96 gap-3');
$modalDialog->addComponent(new Label('API Einstellungen', 'text-xl font-bold text-black'));
$modalDialog->addComponent(new Label(
    'Bitte gib deinen API Key und den Pfad zum Private Key für SSH-Verbindungen ein.',
    'text-sm text-gray-700',
));

$fieldContainer = new Container('flex flex-col gap-1');
$fieldContainer->addComponent(new Label('API Key', 'text-sm text-gray-600'));
$fieldContainer->addComponent($apiKeyInput);
$modalDialog->addComponent($fieldContainer);

$privateKeyFieldContainer = new Container('flex flex-col gap-1');
$privateKeyFieldContainer->addComponent(new Label('Private Key Pfad', 'text-sm text-gray-600'));
$privateKeyFieldContainer->addComponent($privateKeyPathInput);
$modalDialog->addComponent($privateKeyFieldContainer);

$buttonRow = new Container('flex flex-row gap-2 justify-end');
$cancelButton = new Button('Abbrechen', 'px-4 py-2 bg-gray-200 text-black rounded hover:bg-gray-300');
$saveButton = new Button('Speichern', 'px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 flex items-center');
$saveIcon = new Icon(IconName::save, 18, 'text-white mr-2');
$saveButton->setIcon($saveIcon);
$buttonRow->addComponent($cancelButton);
$buttonRow->addComponent($saveButton);
$modalDialog->addComponent($buttonRow);

$modal = new Modal($modalDialog, 'flex items-center justify-center bg-black', 200);

// === 1. MenuBar ===
$menuBar = new MenuBar();

// File Menu
$fileMenu = new Menu(title: 'Datei');
// Settings Menu
$settingsMenu = new Menu(title: 'Einstellungen');
$menuBar->addMenu($fileMenu);
$menuBar->addMenu($settingsMenu);
$mainContainer->addComponent($menuBar);

// === 2. Tab Container (flex-1) ===
$tabContainer = new TabContainer('flex-1');

// Tab 1: Table with server data (Master-Detail Layout)
$tab1 = new Container('flex flex-row p-4 gap-4'); // Changed to flex-row for side-by-side layout

// Left side: Table with refresh button
$leftSide = new Container('flex flex-col gap-2 flex-1'); // flex-1 to take remaining space

// Refresh button (will be configured after loadServers function is defined)
$refreshButton = new Button(
    'Server aktualisieren',
    'flex flex-row gap-2 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700',
);
$refreshIcon = new Icon(IconName::search, 16, 'text-white');
$refreshButton->setIcon($refreshIcon);

$leftSide->addComponent($refreshButton);

// Search input field
$searchInput = new TextInput('Suche...', 'w-full border border-gray-300 rounded px-3 py-2 bg-white text-black mb-2');
$leftSide->addComponent($searchInput);

$table = new Table(style: ' flex-1'); // flex-1 to fill available height but not expand infinitely

$table->setColumns([
    ['key' => 'id', 'title' => 'ID', 'width' => 100],
    ['key' => 'name', 'title' => 'Name', 'width' => 400],
    ['key' => 'status', 'title' => 'Status', 'width' => 120],
    ['key' => 'type', 'title' => 'Typ', 'width' => 120],
    ['key' => 'ipv4', 'title' => 'IPv4'],
]);

// Test data with 63 entries
$testData = [];
for ($i = 1; $i <= 63; $i++) {
    $testData[] = [
        'id' => $i,
        'name' => "Server-{$i}",
        'status' => ($i % 3) === 0 ? 'stopped' : 'running',
        'type' => 'cx' . (11 + (($i % 4) * 10)),
        'ipv4' => sprintf('192.168.%d.%d', floor($i / 255), $i % 255),
    ];
}

// Store current server data (will be updated when API loads servers)
$currentServerData = $testData;
$table->setData($currentServerData);

// Add search functionality
$searchInput->setOnChange(function ($value) use ($table, &$currentServerData) {
    $searchTerm = strtolower(trim($value));

    if (empty($searchTerm)) {
        // Show all data if search is empty
        $table->setData($currentServerData);
    } else {
        // Filter by name
        $filteredData = array_filter($currentServerData, function ($row) use ($searchTerm) {
            return str_contains(strtolower($row['name']), $searchTerm);
        });
        $table->setData(array_values($filteredData));
    }
});

$leftSide->addComponent($table);
$tab1->addComponent($leftSide);

// Right side: Detail panel
$detailPanel = new Container('flex flex-col gap-3 w-80 bg-white border-2 border-gray-300 rounded p-4');
$detailTitle = new Label('Server Details', 'text-xl font-bold text-black mb-2');
$detailPanel->addComponent($detailTitle);

// Detail fields (initially empty)
$detailId = new Label('Bitte einen Server auswählen', 'text-sm text-gray-600');
$detailName = new Label('', 'text-sm text-black');
$detailStatus = new Label('', 'text-sm text-black');
$detailType = new Label('', 'text-sm text-black');
$detailIpv4 = new Label('', 'text-sm text-black');

$detailPanel->addComponent(new Label('ID:', 'text-xs text-gray-500 mt-2'));
$detailPanel->addComponent($detailId);
$detailPanel->addComponent(new Label('Name:', 'text-xs text-gray-500 mt-2'));
$detailPanel->addComponent($detailName);
$detailPanel->addComponent(new Label('Status:', 'text-xs text-gray-500 mt-2'));
$detailPanel->addComponent($detailStatus);
$detailPanel->addComponent(new Label('Typ:', 'text-xs text-gray-500 mt-2'));
$detailPanel->addComponent($detailType);
$detailPanel->addComponent(new Label('IPv4:', 'text-xs text-gray-500 mt-2'));
$detailPanel->addComponent($detailIpv4);

// SFTP Manager Button
$sftpButton = new Button(
    'SFTP Manager öffnen',
    'w-full mt-4 px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700 flex items-center justify-center',
);
$sftpIcon = new Icon(IconName::home, 18, 'text-white mr-2');
$sftpButton->setIcon($sftpIcon);

// Add synchronous click handler to switch tab immediately
$sftpButton->setOnClick(function () use ($tabContainer) {
    $tabContainer->setActiveTab(3); // Switch to SFTP Manager tab immediately
});

$detailPanel->addComponent($sftpButton);

// SSH Terminal Button
$sshTerminalButton = new Button(
    'SSH Terminal öffnen',
    'w-full mt-2 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 flex items-center justify-center',
);
$sshTerminalIcon = new Icon(IconName::home, 18, 'text-white mr-2');
$sshTerminalButton->setIcon($sshTerminalIcon);

// Add click handler to open SSH terminal
$sshTerminalButton->setOnClick(function () use (&$selectedServer, &$currentPrivateKeyPath, &$statusLabel) {
    if ($selectedServer === null) {
        $statusLabel->setText('Kein Server ausgewählt');
        return;
    }

    if (empty($currentPrivateKeyPath) || !file_exists($currentPrivateKeyPath)) {
        $statusLabel->setText('Private Key Pfad nicht konfiguriert');
        return;
    }

    // Build SSH command with private key
    $host = $selectedServer['ipv4'];
    $keyPath = escapeshellarg($currentPrivateKeyPath);
    $sshCommand = "ssh -i {$keyPath} root@{$host}";

    // Try to open terminal with SSH connection
    // Different terminal emulators for different systems
    $terminals = [
        'gnome-terminal -- ' . $sshCommand,
        'konsole -e ' . $sshCommand,
        'xterm -e ' . $sshCommand,
        'x-terminal-emulator -e ' . $sshCommand,
    ];

    $opened = false;
    foreach ($terminals as $terminalCmd) {
        exec($terminalCmd . ' > /dev/null 2>&1 &', $output, $returnCode);
        if ($returnCode === 0) {
            $opened = true;
            $statusLabel->setText('SSH Terminal geöffnet für ' . $selectedServer['name']);
            break;
        }
    }

    if (!$opened) {
        $statusLabel->setText('Konnte kein Terminal öffnen. SSH Befehl: ' . $sshCommand);
    }
});

$detailPanel->addComponent($sshTerminalButton);

$tab1->addComponent($detailPanel);

// Row selection handler - update detail panel
$statusLabel = new Label(
    text: 'Fenster: ' . $window->getViewport()->windowWidth . 'x' . $window->getViewport()->windowHeight,
    style: 'basis-4/8 text-black',
);
$table->setOnRowSelect(function ($index, $row) use (
    &$statusLabel,
    &$selectedServer,
    $detailId,
    $detailName,
    $detailStatus,
    $detailType,
    $detailIpv4,
) {
    if ($row) {
        $statusLabel->setText("Server: {$row['name']} - {$row['status']} ({$row['ipv4']})");

        // Update detail panel
        $detailId->setText("#{$row['id']}");
        $detailName->setText($row['name']);
        $detailStatus->setText($row['status']);
        $detailType->setText($row['type']);
        $detailIpv4->setText($row['ipv4']);

        // Store selected server for SFTP connection
        $selectedServer = $row;
    }
});

// Function to load servers from Hetzner API (only returns simple data, no objects)
// Now uses HetznerClient class thanks to bootstrap.php in async runtime
$loadServersAsync = function () use ($currentApiKey) {
    try {
        if (empty($currentApiKey)) {
            return ['error' => 'Kein API-Key konfiguriert'];
        }

        // Use HetznerClient class (autoloader is available in async runtime)
        $hetznerClient = new \LKDev\HetznerCloud\HetznerAPIClient($currentApiKey);
        $result = ['servers' => []];
        foreach ($hetznerClient->servers()->all() as $server) {
            $result['servers'][] = [
                'id' => $server->id,
                'name' => $server->name,
                'status' => $server->status,
                'type' => $server->serverType->name,
                'ipv4' => $server->publicNet->ipv4->ip,
            ];
        }

        if (isset($result['servers'])) {
            // Return only simple array data
            return ['success' => true, 'servers' => $result['servers'], 'count' => count($result['servers'])];
        }

        return ['error' => 'Unerwartete Antwort'];
    } catch (\Exception $e) {
        return ['error' => 'Exception: ' . $e->getMessage()];
    }
};

// Configure refresh button to load servers asynchronously
$refreshButton->setOnClickAsync(
    $loadServersAsync,
    function ($result) use ($table, $statusLabel, &$currentServerData, $searchInput) {
        // Handle the result in the main thread (can access objects here)
        if (is_array($result)) {
            if (isset($result['error'])) {
                $statusLabel->setText('Fehler: ' . $result['error']);
                echo "Error: {$result['error']}\n";
            } elseif (isset($result['success'], $result['servers'])) {
                // Update current server data
                $currentServerData = $result['servers'];

                // Check if search is active
                $searchTerm = strtolower(trim($searchInput->getValue()));
                if (empty($searchTerm)) {
                    // No search, show all servers
                    $table->setData($currentServerData);
                } else {
                    // Apply search filter to new data
                    $filteredData = array_filter($currentServerData, function ($row) use ($searchTerm) {
                        return str_contains(strtolower($row['name']), $searchTerm);
                    });
                    $table->setData(array_values($filteredData));
                }

                $statusLabel->setText('Server geladen: ' . $result['count'] . ' gefunden');
                echo "Success: {$result['count']} servers loaded\n";
            }
        }
    },
    function ($error) use ($statusLabel) {
        $errorMsg = is_object($error) && method_exists($error, 'getMessage') ? $error->getMessage() : ((string) $error);
        $statusLabel->setText('Async Fehler: ' . $errorMsg);
        echo "Async error: {$errorMsg}\n";
    },
);

$tabContainer->addTab('Server', $tab1);

// Tab 2: SFTP Manager (will be populated dynamically when server is selected)
$sftpTab = new Container('flex flex-row p-4 gap-4 bg-gray-50');

// Left side: Local file browser
$localBrowserContainer = new Container('flex flex-col flex-1 gap-2');
$localBrowserContainer->addComponent(new Label('Lokal', 'text-lg font-bold text-black mb-2'));
$localFileBrowser = new FileBrowser(getcwd(), false, 'flex-1 bg-white border-2 border-gray-300 rounded p-2');
$localBrowserContainer->addComponent($localFileBrowser);

// Right side: Remote file browser
$remoteBrowserContainer = new Container('flex flex-col flex-1 gap-2');
$remoteBrowserContainer->addComponent(new Label('Remote', 'text-lg font-bold text-black mb-2'));
$remoteFileBrowser = new FileBrowser('/', true, 'flex-1 bg-white border-2 border-gray-300 rounded p-2');
$remoteBrowserContainer->addComponent($remoteFileBrowser);

// Connection status label
$connectionStatusLabel = new Label('Nicht verbunden', 'text-sm text-gray-600 italic mb-2');
$remoteBrowserContainer->addComponent($connectionStatusLabel);

$sftpTab->addComponent($localBrowserContainer);
$sftpTab->addComponent($remoteBrowserContainer);

$tabContainer->addTab('SFTP Manager', $sftpTab);

// Remote FileBrowser navigation handler - load directory asynchronously
$remoteFileBrowser->setOnFileSelect(function ($path, $row) use (
    $remoteFileBrowser,
    &$selectedServer,
    &$currentPrivateKeyPath,
    &$statusLabel,
) {
    if (!isset($row['isDir']) || !$row['isDir']) {
        return; // Only handle directories
    }

    // Load directory asynchronously via Button with async handler
    $loadButton = new Button('Load', '');
    $loadButton->setOnClickAsync(
        function () use ($path, &$selectedServer, &$currentPrivateKeyPath) {
            if ($selectedServer === null || empty($currentPrivateKeyPath)) {
                return ['error' => 'Not connected'];
            }

            try {
                $sftp = new \phpseclib3\Net\SFTP($selectedServer['ipv4']);
                $key = \phpseclib3\Crypt\PublicKeyLoader::load(file_get_contents($currentPrivateKeyPath));

                if (!$sftp->login('root', $key)) {
                    return ['error' => 'SFTP Login failed'];
                }

                $files = $sftp->nlist($path);
                if ($files === false) {
                    return ['error' => 'Cannot read directory'];
                }

                $fileList = [];
                foreach ($files as $file) {
                    if ($file === '.' || $file === '..') {
                        continue;
                    }
                    $fullPath = rtrim($path, '/') . '/' . $file;
                    $stat = $sftp->stat($fullPath);
                    $fileList[] = [
                        'name' => $file,
                        'path' => $fullPath,
                        'isDir' => ($stat['type'] ?? 0) === 2,
                        'size' => $stat['size'] ?? 0,
                        'mtime' => $stat['mtime'] ?? 0,
                    ];
                }

                return ['success' => true, 'path' => $path, 'files' => $fileList];
            } catch (\Exception $e) {
                return ['error' => $e->getMessage()];
            }
        },
        function ($result) use ($remoteFileBrowser, &$statusLabel) {
            if (isset($result['error'])) {
                $statusLabel->setText('SFTP Fehler: ' . $result['error']);
                return;
            }

            if (isset($result['success'])) {
                $remoteFileBrowser->setPath($result['path']);
                $remoteFileBrowser->setFileData($result['files']);
            }
        },
        function ($error) use (&$statusLabel) {
            $errorMsg = is_string($error) ? $error : 'Unknown error';
            $statusLabel->setText('SFTP Error: ' . $errorMsg);
        },
    );

    // Trigger the async load
    $loadButton->handleMouseClick(0, 0, 0);
});

// SFTP Button Click Handler - Connect to server and load remote files
$sftpButton->setOnClickAsync(
    function () use (&$selectedServer, &$currentPrivateKeyPath) {
        // This runs in a separate thread
        if ($selectedServer === null) {
            return ['error' => 'Kein Server ausgewählt'];
        }

        if (empty($currentPrivateKeyPath) || !file_exists($currentPrivateKeyPath)) {
            return ['error' => 'Private Key Pfad nicht konfiguriert oder Datei nicht gefunden'];
        }

        try {
            $ssh = new \phpseclib3\Net\SSH2($selectedServer['ipv4']);
            $key = \phpseclib3\Crypt\PublicKeyLoader::load(file_get_contents($currentPrivateKeyPath));

            if (!$ssh->login('root', $key)) {
                return ['error' => 'SSH Login fehlgeschlagen'];
            }

            // Create SFTP connection
            $sftp = new \phpseclib3\Net\SFTP($selectedServer['ipv4']);
            if (!$sftp->login('root', $key)) {
                return ['error' => 'SFTP Login fehlgeschlagen'];
            }

            // Read root directory
            $files = $sftp->nlist('/');
            if ($files === false) {
                return ['error' => 'Kann Root-Verzeichnis nicht lesen'];
            }

            $fileList = [];
            foreach ($files as $file) {
                if ($file === '.' || $file === '..') {
                    continue;
                }
                $stat = $sftp->stat('/' . $file);
                $fileList[] = [
                    'name' => $file,
                    'path' => '/' . $file,
                    'isDir' => ($stat['type'] ?? 0) === 2,
                    'size' => $stat['size'] ?? 0,
                    'mtime' => $stat['mtime'] ?? 0,
                ];
            }

            return [
                'success' => true,
                'server' => $selectedServer,
                'files' => $fileList,
            ];
        } catch (\Exception $e) {
            return ['error' => 'Verbindung fehlgeschlagen: ' . $e->getMessage()];
        }
    },
    function ($result) use ($tabContainer, $remoteFileBrowser, $connectionStatusLabel, &$statusLabel) {
        // This runs in the main thread
        if (isset($result['error'])) {
            $statusLabel->setText('SFTP Fehler: ' . $result['error']);
            return;
        }

        if (isset($result['success']) && $result['success']) {
            $connectionStatusLabel->setText(
                'Verbunden mit: ' . $result['server']['name'] . ' (' . $result['server']['ipv4'] . ')',
            );
            $statusLabel->setText('SFTP Verbindung erfolgreich zu ' . $result['server']['name']);

            // Populate remote file browser with the file list
            $remoteFileBrowser->setPath('/');
            $remoteFileBrowser->setFileData($result['files']);

            // Switch to SFTP Manager tab
            $tabContainer->setActiveTab(1); // Index 3 = SFTP Manager tab
        }
    },
    function ($error) use (&$statusLabel) {
        $errorMsg = is_string($error)
            ? $error
            : (is_object($error) && method_exists($error, 'getMessage') ? $error->getMessage() : 'Unbekannter Fehler');
        $statusLabel->setText('SFTP Async Fehler: ' . $errorMsg);
    },
);

//$mainContainer->addComponent($tabContainer);

// === 3. StatusBar ===
$statusBar = new StatusBar();
$statusBar->addSegment($statusLabel);
$fpsLabel = new Label(
    text: 'FPS: --',
    style: 'basis-1/8 text-black border-l',
);
$statusBar->addSegment(new Label(
    text: 'Zeilen: 10',
    style: 'basis-2/8 text-black border-l',
)); // Fixed width
$statusBar->addSegment($fpsLabel);
$statusBar->addSegment(new Label(
    text: 'Version 1.0',
    style: 'border-l text-black basis-2/8',
));
//$mainContainer->addComponent($statusBar);

$cancelButton->setOnClick(function () use ($menuBar, $modal) {
    $menuBar->closeAllMenus();
    $modal->setVisible(false);
});

$saveButton->setOnClick(function () use (
    $settings,
    &$currentApiKey,
    &$currentPrivateKeyPath,
    $apiKeyInput,
    $privateKeyPathInput,
    $menuBar,
    $modal,
    &$statusLabel,
) {
    $currentApiKey = trim($apiKeyInput->getValue());
    $currentPrivateKeyPath = trim($privateKeyPathInput->getValue());

    // Save to settings
    $settings->set('api_key', $currentApiKey);
    $settings->set('private_key_path', $currentPrivateKeyPath);
    $settings->save();

    if ($statusLabel !== null) {
        $masked = strlen($currentApiKey) > 4
            ? (str_repeat('*', max(0, strlen($currentApiKey) - 4)) . substr($currentApiKey, -4))
            : $currentApiKey;
        $statusLabel->setText('Einstellungen gespeichert: API-Key ' . $masked . ' (' . $settings->getPath() . ')');
    }
    $menuBar->closeAllMenus();
    $modal->setVisible(false);
});

$mainContainer->addComponent($modal);
$window->setOnResize(function (Window $window) use (&$statusLabel) {
    $statusLabel->setText(
        'Fenster: ' . $window->getViewport()->windowWidth . 'x' . $window->getViewport()->windowHeight,
    );
});
$window->setOnFpsChange(function (float $fps) use ($fpsLabel) {
    $fpsLabel->setText(sprintf('FPS: %d', max(0, (int) round($fps))));
});
// Set root and run
$window->setRoot($mainContainer);
$app->addWindow($window);

echo "Windows Application Example started!\n";
echo "Features:\n";
echo "- MenuBar with 'Datei' and 'Einstellungen'\n";
echo "- Tab Container with 3 tabs\n";
echo "- Scrollable Table in first tab\n";
echo "- StatusBar at the bottom\n\n";

$app->run();
