<?php
// api/auth.php
require_once __DIR__ . '/db.php';
session_start();

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

// Helper for sending JSON responses
function sendResponse($data, $statusCode = 200) {
    while (ob_get_level() > 0) {
        ob_end_clean();
    }
    http_response_code($statusCode);
    echo json_encode($data);
    exit;
}

$db = Database::getInstance()->getConnection();
$method = $_SERVER['REQUEST_METHOD'];
$action = isset($_GET['action']) ? $_GET['action'] : '';

// Body data for POST
$input = json_decode(file_get_contents('php://input'), true);

if ($method === 'POST' && $action === 'register') {
    $username = trim($input['username'] ?? '');
    $email = trim($input['email'] ?? '');
    $password = $input['password'] ?? '';

    if (empty($username) || empty($email) || empty($password)) {
        sendResponse(['error' => 'All fields are required.'], 400);
    }

    if (strlen($password) < 6) {
        sendResponse(['error' => 'Password must be at least 6 characters.'], 400);
    }

    // Check if user exists
    $stmt = $db->prepare('SELECT id FROM users WHERE username = ? OR email = ?');
    $stmt->execute([$username, $email]);
    if ($stmt->fetch()) {
        sendResponse(['error' => 'Username or email already exists.'], 409);
    }

    $require_approval = defined('REQUIRE_ADMIN_APPROVAL') && REQUIRE_ADMIN_APPROVAL;
    $is_active = $require_approval ? 0 : 1;

    $hash = password_hash($password, PASSWORD_DEFAULT);
    $stmt = $db->prepare('INSERT INTO users (username, email, password_hash, is_active) VALUES (?, ?, ?, ?)');
    
    try {
        $stmt->execute([$username, $email, $hash, $is_active]);
        $userId = $db->lastInsertId();
        
        if ($require_approval) {
            sendResponse([
                'message' => 'Registration successful. Waiting for administrator approval.',
                'pending_approval' => true
            ], 201);
        } else {
            // Auto-login after registration
            $_SESSION['user_id'] = $userId;
            $_SESSION['username'] = $username;
            $_SESSION['role'] = 'user';

            sendResponse([
                'message' => 'Registration successful.',
                'user' => ['id' => $userId, 'username' => $username, 'role' => 'user']
            ], 201);
        }
    } catch (Exception $e) {
        sendResponse(['error' => 'Registration failed due to server error.'], 500);
    }
} 
elseif ($method === 'POST' && ($action === 'login' || $action === 'mobile_login')) {
    $username = trim($input['username'] ?? '');
    $password = $input['password'] ?? '';

    if (empty($username) || empty($password)) {
        sendResponse(['error' => 'Username and password are required.'], 400);
    }

    $ldap_success = false;
    $auth_method = 'local';
    
    // 1. Zkusit Active Directory (pokud je zapnuto)
    if (defined('USE_LDAP_AUTH') && USE_LDAP_AUTH) {
        $ldapconn = @ldap_connect(LDAP_SERVER);
        if ($ldapconn) {
            @ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
            @ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
            
            // Schválně nesmíme dovolit bind s prázdným heslem (bezpečnostní riziko = anonymní bind)
            if (!empty($password)) {
                $ldapbind = @ldap_bind($ldapconn, $username . LDAP_DOMAIN, $password);
                if ($ldapbind) {
                    $ldap_success = true;
                    $auth_method = 'ldap';
                }
            }
        }
    }

    // Načtemi uživatele tak či tak (pro session i pro fallback DB ověření)
    $stmt = $db->prepare('SELECT id, username, password_hash, role, is_active FROM users WHERE username = ? OR email = ?');
    $stmt->execute([$username, $username]);
    $user = $stmt->fetch();

    $login_success = false;

    if ($ldap_success) {
        // Uživatele ověřilo Active Directory. Nemusíme luštit heslo lokálně.
        if (!$user) {
            // Auto-provisioning do MariaDB: založí uživatele tiše, aby mohl mít nástěnky
            $dummy_hash = password_hash(bin2hex(random_bytes(16)), PASSWORD_DEFAULT);
            $stmtInsert = $db->prepare('INSERT INTO users (username, email, password_hash, role) VALUES (?, ?, ?, ?)');
            $stmtInsert->execute([$username, $username . '@ad.local', $dummy_hash, 'user']);
            
            // Znovu načti nově založeného uživatele
            $stmt->execute([$username, $username]);
            $user = $stmt->fetch();
        }
        $login_success = true;
    } else {
        // 2. Fallback na lokální databázi (pokud LDAP selhalo poznat uživatele, nebo je vyplé)
        if ($user && password_verify($password, $user['password_hash'])) {
            $login_success = true;
            $auth_method = 'local';
        }
    }

    if ($login_success) {
        if ($user['is_active'] == 0) {
            sendResponse(['error' => 'Your account is inactive or pending administrator approval.'], 403);
        }

        if ($action === 'mobile_login') {
            $mobile_token = bin2hex(random_bytes(32));
            $expires = date('Y-m-d H:i:s', strtotime('+5 minutes'));
            $stmtToken = $db->prepare('UPDATE users SET mobile_token = ?, mobile_token_expires = ? WHERE id = ?');
            $stmtToken->execute([$mobile_token, $expires, $user['id']]);

            sendResponse([
                'message' => 'Mobile login successful.',
                'mobile_token' => $mobile_token,
                'user' => [
                    'id' => $user['id'], 
                    'username' => $user['username'],
                    'role' => $user['role'],
                    'auth_method' => $auth_method
                ]
            ]);
        } else {
            $_SESSION['user_id'] = $user['id'];
            $_SESSION['username'] = $user['username'];
            $_SESSION['role'] = $user['role'];
            $_SESSION['auth_method'] = $auth_method; // Uložit info jak se přihlásil

            sendResponse([
                'message' => 'Login successful.',
                'user' => [
                    'id' => $user['id'], 
                    'username' => $user['username'],
                    'role' => $user['role'],
                    'auth_method' => $auth_method
                ]
            ]);
        }
    } else {
        sendResponse(['error' => 'Invalid credentials.'], 401);
    }
}
elseif ($method === 'POST' && $action === 'logout') {
    session_unset();
    session_destroy();
    sendResponse(['message' => 'Logout successful.']);
}
elseif ($method === 'GET' && $action === 'me') {
    if (isset($_SESSION['user_id'])) {
        // Also verify the user is still active just in case
        $stmt = $db->prepare('SELECT is_active, role FROM users WHERE id = ?');
        $stmt->execute([$_SESSION['user_id']]);
        $u = $stmt->fetch();
        
        if (!$u || $u['is_active'] == 0) {
            session_unset();
            session_destroy();
            sendResponse(['error' => 'Your account has been deactivated.'], 401);
        }

        // Refresh role in session just in case it changed
        $_SESSION['role'] = $u['role'];

        sendResponse([
            'user' => [
                'id' => $_SESSION['user_id'],
                'username' => $_SESSION['username'],
                'role' => $u['role'],
                'auth_method' => $_SESSION['auth_method'] ?? 'local'
            ]
        ]);
    } else {
        sendResponse(['error' => 'Not authenticated.'], 401);
    }
}
elseif ($method === 'POST' && $action === 'forgot_password') {
    // Prevent PHP warnings/errors from breaking the JSON response
    error_reporting(0);
    ini_set('display_errors', 0);
    ob_start();

    if (!defined('ENABLE_PASSWORD_RESET') || !ENABLE_PASSWORD_RESET) {
        sendResponse(['error' => 'Password reset is disabled on this server.'], 403);
    }
    
    $email_or_username = trim($input['username'] ?? '');
    if (empty($email_or_username)) {
        sendResponse(['error' => 'Username or email is required.'], 400);
    }

    $stmt = $db->prepare('SELECT id, email, username FROM users WHERE username = ? OR email = ?');
    $stmt->execute([$email_or_username, $email_or_username]);
    $user = $stmt->fetch();

    if (!$user || empty($user['email'])) {
        // Obfuscate response for security (don't reveal if user exists or not)
        sendResponse(['message' => 'alerts.reset_link_sent']);
    }

    $token = bin2hex(random_bytes(32));
    $expires = date('Y-m-d H:i:s', strtotime('+1 hour'));

    $stmtToken = $db->prepare('UPDATE users SET reset_token = ?, reset_expires = ? WHERE id = ?');
    $stmtToken->execute([$token, $expires, $user['id']]);

    // Send Email via PHPMailer
    require_once __DIR__ . '/../assets/vendor/PHPMailer/Exception.php';
    require_once __DIR__ . '/../assets/vendor/PHPMailer/PHPMailer.php';
    require_once __DIR__ . '/../assets/vendor/PHPMailer/SMTP.php';

    $mail = new PHPMailer\PHPMailer\PHPMailer(true);
    try {
        // Použij nativní PHP mail() funkci místo blokovaného SMTP
        $mail->isMail();
        $mail->CharSet = 'UTF-8';

        $mail->setFrom(SMTP_FROM_EMAIL, SMTP_FROM_NAME);
        $mail->addAddress($user['email'], $user['username']);

        // Protocol/Host deduction for the link
        $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
        $host = $_SERVER['HTTP_HOST'];
        $base_url = rtrim(dirname(dirname($_SERVER['PHP_SELF'])), '/\\');
        $reset_link = $protocol . $host . $base_url . '/index.php?reset_token=' . $token;

        $mail->isHTML(true);
        $mail->Subject = 'Reset hesla Kanban';
        $mail->Body    = 'Dobrý den, ' . htmlspecialchars($user['username']) . ',<br><br>' .
                         'Pro resetování zapomenutého hesla do Kanbanu klikněte na odkaz níže (platí 1 hodinu):<br>' .
                         '<a href="' . $reset_link . '">' . $reset_link . '</a><br><br>' .
                         'Pokud jste o reset nežádal/a, můžete tento email ignorovat.';

        $mail->send();
        sendResponse(['message' => 'alerts.reset_link_sent']);
    } catch (Throwable $e) {
        // Silently log or return generic error
        error_log('SMTP Error: ' . $e->getMessage());
        sendResponse(['error' => 'alerts.reset_link_err'], 500);
    }
}
elseif ($method === 'POST' && $action === 'reset_password') {
    $token = $input['token'] ?? '';
    $new_password = $input['password'] ?? '';

    if (empty($token) || strlen($new_password) < 6) {
        sendResponse(['error' => 'Invalid token or password too short.'], 400);
    }

    $stmt = $db->prepare('SELECT id, reset_expires FROM users WHERE reset_token = ?');
    $stmt->execute([$token]);
    $user = $stmt->fetch();

    if (!$user) {
        sendResponse(['error' => 'Invalid or expired reset token.'], 400);
    }

    if (strtotime($user['reset_expires']) < time()) {
        sendResponse(['error' => 'Reset token has expired.'], 400);
    }

    // Reset password
    $hash = password_hash($new_password, PASSWORD_DEFAULT);
    $stmtUpdate = $db->prepare('UPDATE users SET password_hash = ?, reset_token = NULL, reset_expires = NULL WHERE id = ?');
    $stmtUpdate->execute([$hash, $user['id']]);

    sendResponse(['message' => 'Password reset successfully. You can now login.']);
}
else {
    sendResponse(['error' => 'Invalid action or method.'], 400);
}
