<?php

/**
 * CodePress Admin Console - Entry Point
 * Access via: /admin.php?route=login|dashboard|content|config|plugins|users|logout
 */

// Security headers
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: SAMEORIGIN');
header('X-XSS-Protection: 1; mode=block');
header('Referrer-Policy: strict-origin-when-cross-origin');
header_remove('X-Powered-By');

// Load admin components
$appConfig = require __DIR__ . '/../admin-console/config/app.php';
require_once __DIR__ . '/../admin-console/src/AdminAuth.php';

$auth = new AdminAuth($appConfig);

// Routing
$route = $_GET['route'] ?? '';

// Public routes (no auth required)
if ($route === 'login') {
    handleLogin($auth);
    exit;
}

// All other routes require authentication
if (!$auth->isAuthenticated()) {
    header('Location: admin.php?route=login');
    exit;
}

// Authenticated routes
switch ($route) {
    case 'logout':
        $auth->logout();
        header('Location: admin.php?route=login');
        exit;

    case 'dashboard':
    case '':
        handleDashboard($auth, $appConfig);
        break;

    case 'content':
        handleContent($auth, $appConfig);
        break;

    case 'content-edit':
        handleContentEdit($auth, $appConfig);
        break;

    case 'content-new':
        handleContentNew($auth, $appConfig);
        break;

    case 'content-delete':
        handleContentDelete($auth, $appConfig);
        break;

    case 'config':
        handleConfig($auth, $appConfig);
        break;

    case 'plugins':
        handlePlugins($auth, $appConfig);
        break;

    case 'users':
        handleUsers($auth, $appConfig);
        break;

    default:
        header('Location: admin.php?route=dashboard');
        exit;
}

// --- Route Handlers ---

function handleLogin(AdminAuth $auth): void
{
    $error = '';

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $username = trim($_POST['username'] ?? '');
        $password = $_POST['password'] ?? '';

        $result = $auth->login($username, $password);
        if ($result['success']) {
            header('Location: admin.php?route=dashboard');
            exit;
        }
        $error = $result['message'];
    }

    require __DIR__ . '/../admin-console/templates/login.php';
}

function handleDashboard(AdminAuth $auth, array $config): void
{
    $user = $auth->getCurrentUser();
    $csrf = $auth->getCsrfToken();

    // Gather stats
    $contentDir = $config['content_dir'];
    $pluginsDir = $config['plugins_dir'];
    $configJson = $config['config_json'];

    $stats = [
        'pages' => countFiles($contentDir, ['md', 'php', 'html']),
        'directories' => countDirs($contentDir),
        'plugins' => countDirs($pluginsDir),
        'config_exists' => file_exists($configJson),
        'content_size' => formatSize(dirSize($contentDir)),
        'php_version' => PHP_VERSION,
    ];

    // Load site config
    $siteConfig = file_exists($configJson) ? json_decode(file_get_contents($configJson), true) : [];

    require __DIR__ . '/../admin-console/templates/layout.php';
}

function handleContent(AdminAuth $auth, array $config): void
{
    $user = $auth->getCurrentUser();
    $csrf = $auth->getCsrfToken();
    $contentDir = $config['content_dir'];
    $subdir = $_GET['dir'] ?? '';

    // Prevent path traversal
    $subdir = str_replace(['../', '..\\'], '', $subdir);
    $fullPath = rtrim($contentDir, '/') . '/' . $subdir;

    if (!is_dir($fullPath)) {
        $fullPath = $contentDir;
        $subdir = '';
    }

    $items = scanContentDir($fullPath, $subdir);
    $route = 'content';

    require __DIR__ . '/../admin-console/templates/layout.php';
}

function handleContentEdit(AdminAuth $auth, array $config): void
{
    $user = $auth->getCurrentUser();
    $csrf = $auth->getCsrfToken();
    $contentDir = $config['content_dir'];
    $file = $_GET['file'] ?? '';
    $file = str_replace(['../', '..\\'], '', $file);
    $filePath = rtrim($contentDir, '/') . '/' . $file;
    $message = '';
    $messageType = '';

    // Validate path
    $realPath = realpath($filePath);
    $realContentDir = realpath($contentDir);
    if (!$realPath || !$realContentDir || strpos($realPath, $realContentDir) !== 0) {
        header('Location: admin.php?route=content');
        exit;
    }

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        if (!$auth->verifyCsrf($_POST['csrf_token'] ?? '')) {
            $message = 'Ongeldige CSRF token.';
            $messageType = 'danger';
        } else {
            $content = $_POST['content'] ?? '';
            file_put_contents($filePath, $content);
            $message = 'Bestand opgeslagen.';
            $messageType = 'success';
        }
    }

    $fileContent = file_get_contents($filePath);
    $fileName = basename($filePath);
    $fileExt = pathinfo($filePath, PATHINFO_EXTENSION);
    $route = 'content-edit';

    require __DIR__ . '/../admin-console/templates/layout.php';
}

function handleContentNew(AdminAuth $auth, array $config): void
{
    $user = $auth->getCurrentUser();
    $csrf = $auth->getCsrfToken();
    $contentDir = $config['content_dir'];
    $dir = $_GET['dir'] ?? '';
    $dir = str_replace(['../', '..\\'], '', $dir);
    $message = '';
    $messageType = '';

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        if (!$auth->verifyCsrf($_POST['csrf_token'] ?? '')) {
            $message = 'Ongeldige CSRF token.';
            $messageType = 'danger';
        } else {
            $filename = trim($_POST['filename'] ?? '');
            $content = $_POST['content'] ?? '';
            $type = $_POST['type'] ?? 'md';

            if (empty($filename)) {
                $message = 'Bestandsnaam is verplicht.';
                $messageType = 'danger';
            } else {
                // Sanitize filename
                $filename = preg_replace('/[^a-zA-Z0-9._-]/', '-', $filename);
                if (!preg_match('/\.(md|php|html)$/', $filename)) {
                    $filename .= '.' . $type;
                }
                $targetDir = rtrim($contentDir, '/') . '/' . $dir;
                $filePath = $targetDir . '/' . $filename;

                if (file_exists($filePath)) {
                    $message = 'Bestand bestaat al.';
                    $messageType = 'danger';
                } else {
                    if (!is_dir($targetDir)) {
                        mkdir($targetDir, 0755, true);
                    }
                    file_put_contents($filePath, $content);
                    header('Location: admin.php?route=content&dir=' . urlencode($dir));
                    exit;
                }
            }
        }
    }

    $route = 'content-new';
    require __DIR__ . '/../admin-console/templates/layout.php';
}

function handleContentDelete(AdminAuth $auth, array $config): void
{
    $contentDir = $config['content_dir'];
    $file = $_GET['file'] ?? '';
    $file = str_replace(['../', '..\\'], '', $file);
    $filePath = rtrim($contentDir, '/') . '/' . $file;

    $realPath = realpath($filePath);
    $realContentDir = realpath($contentDir);

    if ($_SERVER['REQUEST_METHOD'] === 'POST'
        && $auth->verifyCsrf($_POST['csrf_token'] ?? '')
        && $realPath && $realContentDir
        && strpos($realPath, $realContentDir) === 0
    ) {
        if (is_file($filePath)) {
            unlink($filePath);
        }
    }

    $dir = dirname($file);
    header('Location: admin.php?route=content&dir=' . urlencode($dir === '.' ? '' : $dir));
    exit;
}

function handleConfig(AdminAuth $auth, array $config): void
{
    $user = $auth->getCurrentUser();
    $csrf = $auth->getCsrfToken();
    $configJson = $config['config_json'];
    $message = '';
    $messageType = '';

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        if (!$auth->verifyCsrf($_POST['csrf_token'] ?? '')) {
            $message = 'Ongeldige CSRF token.';
            $messageType = 'danger';
        } else {
            $jsonContent = $_POST['config_content'] ?? '';
            $parsed = json_decode($jsonContent, true);
            if ($parsed === null && json_last_error() !== JSON_ERROR_NONE) {
                $message = 'Ongeldige JSON: ' . json_last_error_msg();
                $messageType = 'danger';
            } else {
                file_put_contents($configJson, json_encode($parsed, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
                $message = 'Configuratie opgeslagen.';
                $messageType = 'success';
                $jsonContent = null; // reload from file
            }
        }
    }

    $siteConfig = file_exists($configJson) ? file_get_contents($configJson) : '{}';
    if (isset($jsonContent)) {
        $siteConfig = $jsonContent;
    }

    $route = 'config';
    require __DIR__ . '/../admin-console/templates/layout.php';
}

function handlePlugins(AdminAuth $auth, array $config): void
{
    $user = $auth->getCurrentUser();
    $csrf = $auth->getCsrfToken();
    $pluginsDir = $config['plugins_dir'];
    $plugins = [];

    if (is_dir($pluginsDir)) {
        foreach (scandir($pluginsDir) as $item) {
            if ($item[0] === '.') continue;
            $pluginPath = $pluginsDir . '/' . $item;
            if (!is_dir($pluginPath)) continue;

            $hasConfig = file_exists($pluginPath . '/config.json');
            $pluginConfig = $hasConfig ? json_decode(file_get_contents($pluginPath . '/config.json'), true) : [];
            $hasMainFile = file_exists($pluginPath . '/' . $item . '.php');
            $hasReadme = file_exists($pluginPath . '/README.md');

            $plugins[] = [
                'name' => $item,
                'path' => $pluginPath,
                'enabled' => $pluginConfig['enabled'] ?? true,
                'config' => $pluginConfig,
                'has_config' => $hasConfig,
                'has_main' => $hasMainFile,
                'has_readme' => $hasReadme,
            ];
        }
    }

    $route = 'plugins';
    require __DIR__ . '/../admin-console/templates/layout.php';
}

function handleUsers(AdminAuth $auth, array $config): void
{
    $user = $auth->getCurrentUser();
    $csrf = $auth->getCsrfToken();
    $message = '';
    $messageType = '';

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        if (!$auth->verifyCsrf($_POST['csrf_token'] ?? '')) {
            $message = 'Ongeldige CSRF token.';
            $messageType = 'danger';
        } else {
            $action = $_POST['action'] ?? '';

            if ($action === 'add') {
                $result = $auth->addUser(
                    trim($_POST['username'] ?? ''),
                    $_POST['password'] ?? '',
                    $_POST['role'] ?? 'admin'
                );
                $message = $result['message'];
                $messageType = $result['success'] ? 'success' : 'danger';
            } elseif ($action === 'delete') {
                $result = $auth->deleteUser($_POST['delete_username'] ?? '');
                $message = $result['message'];
                $messageType = $result['success'] ? 'success' : 'danger';
            } elseif ($action === 'change_password') {
                $result = $auth->changePassword(
                    $_POST['pw_username'] ?? '',
                    $_POST['new_password'] ?? ''
                );
                $message = $result['message'];
                $messageType = $result['success'] ? 'success' : 'danger';
            }
        }
    }

    $users = $auth->getUsers();
    $route = 'users';
    require __DIR__ . '/../admin-console/templates/layout.php';
}

// --- Helper functions ---

function countFiles(string $dir, array $extensions): int
{
    $count = 0;
    if (!is_dir($dir)) return 0;
    $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS));
    foreach ($iterator as $file) {
        if ($file->isFile() && in_array($file->getExtension(), $extensions)) {
            $count++;
        }
    }
    return $count;
}

function countDirs(string $dir): int
{
    if (!is_dir($dir)) return 0;
    $count = 0;
    foreach (scandir($dir) as $item) {
        if ($item[0] !== '.' && is_dir($dir . '/' . $item)) $count++;
    }
    return $count;
}

function dirSize(string $dir): int
{
    $size = 0;
    if (!is_dir($dir)) return 0;
    $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS));
    foreach ($iterator as $file) {
        if ($file->isFile()) $size += $file->getSize();
    }
    return $size;
}

function formatSize(int $bytes): string
{
    $units = ['B', 'KB', 'MB', 'GB'];
    $i = 0;
    while ($bytes >= 1024 && $i < count($units) - 1) {
        $bytes /= 1024;
        $i++;
    }
    return round($bytes, 1) . ' ' . $units[$i];
}

function scanContentDir(string $fullPath, string $subdir): array
{
    $items = [];
    if (!is_dir($fullPath)) return $items;

    foreach (scandir($fullPath) as $item) {
        if ($item[0] === '.') continue;
        $itemPath = $fullPath . '/' . $item;
        $relativePath = $subdir ? $subdir . '/' . $item : $item;

        $items[] = [
            'name' => $item,
            'path' => $relativePath,
            'is_dir' => is_dir($itemPath),
            'size' => is_file($itemPath) ? formatSize(filesize($itemPath)) : '',
            'modified' => date('d-m-Y H:i', filemtime($itemPath)),
            'extension' => is_file($itemPath) ? pathinfo($item, PATHINFO_EXTENSION) : '',
        ];
    }

    // Sort: directories first, then files alphabetically
    usort($items, function ($a, $b) {
        if ($a['is_dir'] !== $b['is_dir']) return $b['is_dir'] - $a['is_dir'];
        return strcasecmp($a['name'], $b['name']);
    });

    return $items;
}
