<?php
if (session_status() !== PHP_SESSION_ACTIVE) {
    session_start();
}

function adminCount() {
    try {
        $pdo = getDBConnection();
        return (int)$pdo->query("SELECT COUNT(*) FROM admin_users WHERE is_active = 1")->fetchColumn();
    } catch (Throwable $e) {
        return 0;
    }
}

function isAdminSetupRequired() {
    return adminCount() === 0;
}

function isLoggedIn() {
    return !empty($_SESSION['admin_user_id']);
}

function currentAdminUser() {
    if (!isLoggedIn()) return null;
    try {
        $pdo = getDBConnection();
        $stmt = $pdo->prepare("SELECT id, username, display_name, role, is_active, last_login_at FROM admin_users WHERE id = :id AND is_active = 1");
        $stmt->execute([':id' => (int)$_SESSION['admin_user_id']]);
        $user = $stmt->fetch();
        if (!$user) {
            logoutAdmin(false);
            return null;
        }
        return $user;
    } catch (Throwable $e) {
        return null;
    }
}

function adminRoleLabels() {
    return [
        'super_admin' => '최고관리자',
        'admin' => '최고관리자',
        'manager' => '일반관리자',
        'music_manager' => '음악관리자',
        'metadata_manager' => '메타데이터관리자',
        'backup_manager' => '백업관리자',
        'log_viewer' => '로그조회자',
        'readonly' => '읽기전용관리자',
    ];
}

function adminPermissionMap() {
    $all = [
        'admin_home', 'diagnostics_view', 'performance_view', 'alert_view',
        'music_scan', 'music_manage', 'missing_files_manage', 'duplicates_manage',
        'metadata_view', 'metadata_edit', 'metadata_bulk_edit', 'tag_manage', 'lyrics_manage', 'rating_manage',
        'smart_organize', 'name_merge', 'playlist_manage',
        'backup_view', 'backup_create', 'backup_download', 'backup_delete', 'backup_restore', 'export_data', 'import_data',
        'log_view', 'log_delete', 'audit_view',
        'settings_manage', 'maintenance_run', 'admin_manage',
    ];
    return [
        'super_admin' => $all,
        'admin' => $all,
        'manager' => array_values(array_diff($all, ['admin_manage', 'backup_restore', 'log_delete'])),
        'music_manager' => ['admin_home', 'diagnostics_view', 'music_scan', 'music_manage', 'missing_files_manage', 'duplicates_manage', 'playlist_manage'],
        'metadata_manager' => ['admin_home', 'diagnostics_view', 'metadata_view', 'metadata_edit', 'metadata_bulk_edit', 'tag_manage', 'lyrics_manage', 'rating_manage', 'smart_organize', 'name_merge'],
        'backup_manager' => ['admin_home', 'diagnostics_view', 'backup_view', 'backup_create', 'backup_download', 'backup_delete', 'backup_restore', 'export_data', 'import_data'],
        'log_viewer' => ['admin_home', 'diagnostics_view', 'performance_view', 'alert_view', 'log_view', 'audit_view'],
        'readonly' => ['admin_home', 'diagnostics_view', 'performance_view', 'alert_view', 'log_view', 'audit_view', 'metadata_view', 'backup_view'],
    ];
}

function currentAdminRole() {
    $user = currentAdminUser();
    $role = $user['role'] ?? 'readonly';
    return array_key_exists($role, adminPermissionMap()) ? $role : 'readonly';
}

function hasPermission($permission) {
    if (!isLoggedIn()) return false;
    $role = currentAdminRole();
    $permissions = adminPermissionMap()[$role] ?? [];
    return in_array((string)$permission, $permissions, true);
}

function maskSensitiveLogMessage($message) {
    $message = (string)$message;
    $message = preg_replace('/[A-Z]:[\\\\\/][^\s"\']+/i', '[path]', $message);
    return $message;
}

function writeAuditLog($action, $summary = '', $result = 'success', $severity = 'info', $targetType = null, $targetId = null) {
    $summary = maskSensitiveLogMessage($summary);
    logAdminAction((string)$action, $summary);
    if (function_exists('writeAppLog')) {
        writeAppLog($severity, 'audit', $summary !== '' ? $summary : (string)$action, [
            'action' => (string)$action,
            'result' => (string)$result,
            'target_type' => $targetType,
            'target_id' => $targetId,
            'admin_id' => $_SESSION['admin_user_id'] ?? null,
            'admin_name' => $_SESSION['admin_username'] ?? null,
        ]);
    }
}

function denyAdminAccess($permission = null) {
    $message = '권한이 없습니다.';
    writeAuditLog('permission_denied', 'Permission denied: ' . (string)$permission . ' / ' . currentRelativeUrl(), 'denied', 'warning', 'permission', $permission);
    if (isAjaxRequest()) {
        header('Content-Type: application/json; charset=utf-8');
        http_response_code(403);
        echo json_encode(['success' => false, 'message' => $message], JSON_UNESCAPED_UNICODE);
        exit;
    }
    http_response_code(403);
    $base = authBasePath();
    echo '<!doctype html><html lang="ko"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>권한 없음</title><link rel="stylesheet" href="' . htmlspecialchars($base, ENT_QUOTES, 'UTF-8') . 'assets/css/style.css"></head><body><main class="auth-page"><section class="auth-card"><div class="auth-heading"><i class="fa-solid fa-lock"></i><h1>권한이 없습니다</h1><p>이 관리자 기능을 사용할 권한이 없습니다.</p></div><a class="btn btn-primary" href="' . htmlspecialchars($base, ENT_QUOTES, 'UTF-8') . 'admin/index.php">관리 허브로 이동</a></section></main></body></html>';
    exit;
}

function requirePermission($permission) {
    requireAdmin();
    if (!hasPermission($permission)) denyAdminAccess($permission);
}

function adminDisplayName() {
    $user = currentAdminUser();
    if (!$user) return '';
    return trim((string)($user['display_name'] ?: $user['username']));
}

function safeReturnUrl($returnUrl, $default = 'admin/index.php') {
    $returnUrl = trim((string)$returnUrl);
    if ($returnUrl === '') return $default;
    if (preg_match('/^[a-z][a-z0-9+.-]*:/i', $returnUrl)) return $default;
    if (strpos($returnUrl, '//') === 0) return $default;
    $returnUrl = str_replace('\\', '/', $returnUrl);
    $returnUrl = ltrim($returnUrl, '/');
    if (strpos($returnUrl, '..') !== false) return $default;
    return $returnUrl;
}

function currentRelativeUrl() {
    $script = str_replace('\\', '/', (string)($_SERVER['SCRIPT_NAME'] ?? ''));
    $parts = explode('/music/', $script, 2);
    $path = isset($parts[1]) ? $parts[1] : ltrim($script, '/');
    $query = (string)($_SERVER['QUERY_STRING'] ?? '');
    return $query !== '' ? $path . '?' . $query : $path;
}

function requireAdmin() {
    if (isAdminSetupRequired()) {
        header('Location: ' . authBasePath() . 'admin/setup_admin.php');
        exit;
    }
    if (!isLoggedIn() || !currentAdminUser()) {
        $return = safeReturnUrl(currentRelativeUrl());
        if (isAjaxRequest()) {
            header('Content-Type: application/json; charset=utf-8');
            http_response_code(401);
            echo json_encode(['success' => false, 'message' => '로그인이 필요합니다.'], JSON_UNESCAPED_UNICODE);
            exit;
        }
        header('Location: ' . authBasePath() . 'login.php?return=' . urlencode($return));
        exit;
    }
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    header('Pragma: no-cache');
}

function requireLogin() {
    requireAdmin();
}

function redirectIfLoggedIn() {
    if (isLoggedIn() && currentAdminUser()) {
        header('Location: admin/index.php');
        exit;
    }
}

function loginAdmin($user) {
    session_regenerate_id(true);
    $_SESSION['admin_user_id'] = (int)$user['id'];
    $_SESSION['admin_username'] = (string)$user['username'];
}

function logoutAdmin($log = true) {
    if ($log && isLoggedIn()) {
        logAdminAction('logout', '관리자 로그아웃');
    }
    $_SESSION = [];
    if (ini_get('session.use_cookies')) {
        $params = session_get_cookie_params();
        setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
    }
    session_destroy();
}

function getCsrfToken() {
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
}

function csrfInput() {
    return '<input type="hidden" name="csrf_token" value="' . htmlspecialchars(getCsrfToken(), ENT_QUOTES, 'UTF-8') . '">';
}

function verifyCsrfToken($token = null) {
    $token = $token ?? ($_POST['csrf_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '');
    return is_string($token) && isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
}

function requireCsrfToken() {
    if (!verifyCsrfToken()) {
        if (isAjaxRequest()) {
            header('Content-Type: application/json; charset=utf-8');
            http_response_code(403);
            echo json_encode(['success' => false, 'message' => '보안 토큰이 올바르지 않습니다. 새로고침 후 다시 시도하세요.'], JSON_UNESCAPED_UNICODE);
            exit;
        }
        http_response_code(403);
        die('보안 토큰이 올바르지 않습니다. 새로고침 후 다시 시도하세요.');
    }
}

function isAjaxRequest() {
    $accept = (string)($_SERVER['HTTP_ACCEPT'] ?? '');
    $requestedWith = (string)($_SERVER['HTTP_X_REQUESTED_WITH'] ?? '');
    return stripos($accept, 'application/json') !== false || strtolower($requestedWith) === 'xmlhttprequest';
}

function authBasePath() {
    $script = str_replace('\\', '/', (string)($_SERVER['SCRIPT_NAME'] ?? ''));
    return strpos($script, '/admin/') !== false ? '../' : './';
}

function logAdminAction($actionType, $message = null, $adminUserId = null) {
    try {
        $pdo = getDBConnection();
        if ($adminUserId === null && !empty($_SESSION['admin_user_id'])) {
            $adminUserId = (int)$_SESSION['admin_user_id'];
        }
        $stmt = $pdo->prepare("
            INSERT INTO admin_logs (admin_user_id, action_type, message, ip_address, user_agent)
            VALUES (:admin_user_id, :action_type, :message, :ip_address, :user_agent)
        ");
        $stmt->execute([
            ':admin_user_id' => $adminUserId,
            ':action_type' => $actionType,
            ':message' => $message,
            ':ip_address' => $_SERVER['REMOTE_ADDR'] ?? null,
            ':user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? null,
        ]);
    } catch (Throwable $e) {
        // Logging must never break user-facing flows.
    }
}
