<?php
declare(strict_types=1);

require_once __DIR__ . '/env.php';

/**
 * App-Login (schöne Login-Seite) für /adminer.
 * Nutzer werden in einer MySQL-Tabelle gespeichert.
 *
 * Alles liegt in der DB "FabianWebsite".
 */

function adminer_app_session_start()
{
    // CLI: keine Sessions/Headers
    if (PHP_SAPI === 'cli') {
        return;
    }

    if (session_status() === PHP_SESSION_NONE) {
        ini_set('session.cookie_httponly', '1');
        if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
            ini_set('session.cookie_secure', '1');
        }
        session_start();
    }
}

function adminer_app_config()
{
    $vars = env_load(dirname(__DIR__) . '/.env');

    // DB fest auf FabianWebsite, wie gewünscht.
    $cfg = [
        'host' => (string)env_get($vars, 'DB_SERVERNAME', 'localhost'),
        'port' => (int)env_get($vars, 'DB_PORT', '3306'),
        'user' => (string)env_get($vars, 'DB_USERNAME', ''),
        'pass' => (string)env_get($vars, 'DB_PASSWORD', ''),
        'db'   => 'FabianWebsite',
        // Registrierung optional abschaltbar
        'allow_register' => ((string)env_get($vars, 'ADMINER_ALLOW_REGISTER', '1')) !== '0',
    ];

    return $cfg;
}

function adminer_app_pdo()
{
    $cfg  = adminer_app_config();

    if ($cfg['host'] === '' || (int)$cfg['port'] <= 0 || $cfg['user'] === '' || $cfg['db'] === '') {
        throw new RuntimeException('DB_* ist in .env nicht vollständig gesetzt (für Admin-Login-User-Store).');
    }

    $dsn = sprintf('mysql:host=%s;port=%d;dbname=%s;charset=utf8mb4', $cfg['host'], (int)$cfg['port'], $cfg['db']);

    return new PDO($dsn, $cfg['user'], $cfg['pass'], [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ]);
}

function adminer_validate_username($u)
{
    $u = trim((string)$u);
    if ($u === '') return [false, 'Benutzername darf nicht leer sein.'];
    if (strlen($u) < 3) return [false, 'Benutzername ist zu kurz (min. 3 Zeichen).'];
    if (strlen($u) > 50) return [false, 'Benutzername ist zu lang (max. 50 Zeichen).'];
    if (!preg_match('/^[A-Za-z0-9_.-]+$/', $u)) return [false, 'Nur Buchstaben, Zahlen, Punkt, Unterstrich und Minus sind erlaubt.'];
    return [true, null];
}

function adminer_app_bootstrap()
{
    $pdo = adminer_app_pdo();

    $pdo->exec(
        'CREATE TABLE IF NOT EXISTS adminer_users ('
        . 'id INT AUTO_INCREMENT PRIMARY KEY,'
        . 'username VARCHAR(190) NOT NULL UNIQUE,'
        . 'password_hash VARCHAR(255) NOT NULL,'
        . 'is_admin TINYINT(1) NOT NULL DEFAULT 0,'
        . 'created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP'
        . ') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4'
    );

    // Migration: falls Tabelle bereits existiert (alte Version ohne is_admin)
    try {
        $col = $pdo->query("SHOW COLUMNS FROM adminer_users LIKE 'is_admin'")->fetch();
        if (!$col) {
            $pdo->exec('ALTER TABLE adminer_users ADD COLUMN is_admin TINYINT(1) NOT NULL DEFAULT 0');
        }
    } catch (Throwable $e) {
        // Wenn ALTER scheitert, lieber deutlich machen
        throw new RuntimeException('Konnte adminer_users nicht migrieren (is_admin): ' . $e->getMessage());
    }

    // Optional: auto-seed from .env ADMINER_APP_SEED_USER/PASS
    $vars = env_load(dirname(__DIR__) . '/.env');
    $seedUser = env_get($vars, 'ADMINER_APP_SEED_USER', '');
    $seedPass = env_get($vars, 'ADMINER_APP_SEED_PASS', '');

    if ($seedUser !== '' && $seedPass !== '') {
        $stmt = $pdo->prepare('SELECT id FROM adminer_users WHERE username = ?');
        $stmt->execute([(string)$seedUser]);
        $id = $stmt->fetchColumn();
        if (!$id) {
            $hash = password_hash((string)$seedPass, PASSWORD_DEFAULT);
            $ins = $pdo->prepare('INSERT INTO adminer_users (username, password_hash, is_admin) VALUES (?, ?, 1)');
            $ins->execute([(string)$seedUser, $hash]);
        } else {
            // sicherstellen, dass Seed-User Admin ist
            $upd = $pdo->prepare('UPDATE adminer_users SET is_admin = 1 WHERE id = ?');
            $upd->execute([(int)$id]);
        }
    }
}

function adminer_app_is_logged_in()
{
    adminer_app_session_start();
    if (PHP_SAPI === 'cli') {
        return false;
    }
    return !empty($_SESSION['adminer_app']['ok']);
}

function adminer_app_logout()
{
    adminer_app_session_start();
    if (PHP_SAPI === 'cli') {
        return;
    }
    unset($_SESSION['adminer_app']);
}

function adminer_app_try_login($username, $password)
{
    $username = trim((string)$username);
    $password = (string)$password;

    if ($username === '' || $password === '') {
        return ['ok' => false, 'error' => 'Bitte Benutzername und Passwort eingeben.'];
    }

    $pdo = adminer_app_pdo();
    $stmt = $pdo->prepare('SELECT id, password_hash, is_admin FROM adminer_users WHERE username = ?');
    $stmt->execute([$username]);
    $row = $stmt->fetch();

    if (!$row || empty($row['password_hash']) || !password_verify($password, (string)$row['password_hash'])) {
        return ['ok' => false, 'error' => 'Login fehlgeschlagen.'];
    }

    // Erst nach Verifizierung erlauben
    if (empty($row['is_admin'])) {
        return ['ok' => false, 'error' => 'Dein Konto ist noch nicht verifiziert. Bitte lasse dich von einem Server-Administrator freischalten.'];
    }

    adminer_app_session_start();
    if (PHP_SAPI !== 'cli') {
        $_SESSION['adminer_app'] = [
            'ok' => true,
            'username' => $username,
            'uid' => (int)$row['id'],
            'is_admin' => (bool)$row['is_admin'],
        ];
    }

    return ['ok' => true, 'error' => null];
}

function adminer_app_allow_register()
{
    $cfg = adminer_app_config();
    return !empty($cfg['allow_register']);
}

function adminer_app_try_register($username, $password, $password2)
{
    if (!adminer_app_allow_register()) {
        return ['ok' => false, 'error' => 'Registrierung ist deaktiviert.'];
    }

    list($ok, $msg) = adminer_validate_username($username);
    if (!$ok) return ['ok' => false, 'error' => $msg];

    $password = (string)$password;
    $password2 = (string)$password2;

    if (strlen($password) < 8) {
        return ['ok' => false, 'error' => 'Passwort ist zu kurz (min. 8 Zeichen).'];
    }
    if ($password !== $password2) {
        return ['ok' => false, 'error' => 'Passwörter stimmen nicht überein.'];
    }

    $pdo = adminer_app_pdo();

    // Unique check
    $stmt = $pdo->prepare('SELECT id FROM adminer_users WHERE username = ?');
    $stmt->execute([trim((string)$username)]);
    if ($stmt->fetchColumn()) {
        return ['ok' => false, 'error' => 'Benutzername ist bereits vergeben.'];
    }

    // Standard: unverifiziert (is_admin=0)
    $hash = password_hash($password, PASSWORD_DEFAULT);
    $ins = $pdo->prepare('INSERT INTO adminer_users (username, password_hash, is_admin) VALUES (?, ?, 0)');
    $ins->execute([trim((string)$username), $hash]);

    return ['ok' => true, 'error' => null];
}

