<?php
/**
 * Legacy gridAuth* actions for modules/core/storageAdapter.js (BASE_URL ?action=…).
 * Maps server-side Antara auth store + settings.json (loginScreen) to the old
 * { success, data } shape. WebAuthn here is deprecated; use /login/ + core/auth/api.php.
 */

declare(strict_types=1);

/**
 * POST mutators from the legacy grid: accept Antara session CSRF (header or JSON)
 * or same-origin / same-site fetch metadata / Referer host match.
 */
function antara_gridauth_csrf_or_same_site(array $body): bool
{
    require_once __DIR__ . '/../security/csrf.php';
    $hdr = (string)($_SERVER['HTTP_X_CSRF_TOKEN'] ?? '');
    $bod = isset($body['csrf']) && is_string($body['csrf']) ? $body['csrf'] : '';
    $token = $hdr !== '' ? $hdr : $bod;
    if ($token !== '' && AntaraCsrf::isValid($token)) {
        return true;
    }
    $sf = strtolower((string)($_SERVER['HTTP_SEC_FETCH_SITE'] ?? ''));
    if ($sf === 'same-origin' || $sf === 'same-site') {
        return true;
    }
    $ref = (string)($_SERVER['HTTP_REFERER'] ?? '');
    if ($ref === '') {
        return false;
    }
    $rh = parse_url($ref, PHP_URL_HOST);
    $hh = $_SERVER['HTTP_HOST'] ?? '';
    if (!is_string($rh) || $rh === '' || !is_string($hh) || $hh === '') {
        return false;
    }
    $rh = preg_replace('/:\d+$/', '', strtolower($rh));
    $hh = preg_replace('/:\d+$/', '', strtolower($hh));

    return $rh === $hh;
}

function antara_gridauth_handle_and_exit(): void
{
    $action = (string)($_GET['action'] ?? '');
    if ($action === '' || strncmp($action, 'gridAuth', 8) !== 0) {
        return;
    }

    require_once __DIR__ . '/bootstrap_auth.php';

    if (AntaraStore::tryConfigRead() === null) {
        http_response_code(503);
        header('Content-Type: application/json; charset=utf-8');
        header('Cache-Control: no-store, no-cache, must-revalidate');
        echo json_encode([
            'success' => false,
            'error'   => 'Cofre criptográfico ilegible. Abre la aplicación en el navegador para recuperar Flexia.',
            'code'    => 'VAULT_UNREADABLE',
        ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        exit;
    }

    header('Content-Type: application/json; charset=utf-8');
    header('Cache-Control: no-store, no-cache, must-revalidate');

    $method = strtoupper($_SERVER['REQUEST_METHOD'] ?? 'GET');

    /** @var array $settingsFile, $settingsBackupFile, $defaultSettings from index bootstrap */
    global $settingsFile, $settingsBackupFile, $defaultSettings;

    $readSettings = static function (): array {
        global $settingsFile, $settingsBackupFile, $defaultSettings;
        if (isset($settingsFile, $settingsBackupFile, $defaultSettings) && function_exists('grid_read_settings_for_api')) {
            return grid_read_settings_for_api($settingsFile, $settingsBackupFile, $defaultSettings);
        }
        if (!defined('GRID_ROOT')) {
            define('GRID_ROOT', dirname(__DIR__, 2));
        }
        if (!function_exists('grid_read_settings_for_api')) {
            require_once GRID_ROOT . '/includes/settings_helpers.php';
        }
        $sf = GRID_ROOT . DIRECTORY_SEPARATOR . 'settings.json';
        $bk = GRID_ROOT . DIRECTORY_SEPARATOR . 'settings.json.bak';
        $def = [
            'backgroundType' => 'file',
            'backgroundUrl' => '',
            'backgroundImages' => [],
            'backgroundVideos' => [],
            'videoPlayMode' => 'random',
            'slideshowEnabled' => false,
            'slideshowInterval' => 5,
            'youtubeBackground' => '',
        ];
        return grid_read_settings_for_api($sf, $bk, $def);
    };

    $persistSettings = static function (array $merged): void {
        global $settingsFile, $settingsBackupFile;
        if (isset($settingsFile, $settingsBackupFile) && function_exists('grid_persist_settings')) {
            grid_persist_settings($settingsFile, $settingsBackupFile, $merged);
            return;
        }
        if (!defined('GRID_ROOT')) {
            define('GRID_ROOT', dirname(__DIR__, 2));
        }
        if (!function_exists('grid_persist_settings')) {
            require_once GRID_ROOT . '/includes/settings_helpers.php';
        }
        $sf = GRID_ROOT . DIRECTORY_SEPARATOR . 'settings.json';
        $bk = GRID_ROOT . DIRECTORY_SEPARATOR . 'settings.json.bak';
        grid_persist_settings($sf, $bk, $merged);
    };

    $defaultLoginScreen = static function (): array {
        return [
            'bgType' => 'default',
            'videoUrl' => '',
            'imageUrls' => [],
            'slideshowMode' => 'sequential',
            'fixedImageIndex' => 0,
            'slideshowIntervalSec' => 18,
        ];
    };

    $loginScreenFromSettings = static function (array $s) use ($defaultLoginScreen): array {
        if (isset($s['loginScreen']) && is_array($s['loginScreen'])) {
            return array_merge($defaultLoginScreen(), $s['loginScreen']);
        }
        $images = [];
        if (!empty($s['backgroundImages']) && is_array($s['backgroundImages'])) {
            foreach ($s['backgroundImages'] as $it) {
                if (is_string($it) && $it !== '') {
                    $images[] = $it;
                }
            }
        }
        $video = '';
        if (!empty($s['youtubeBackground'])) {
            $video = (string)$s['youtubeBackground'];
        } elseif (!empty($s['backgroundUrl'])) {
            $video = (string)$s['backgroundUrl'];
        }
        $bgType = 'default';
        $bt = strtolower((string)($s['backgroundType'] ?? 'file'));
        if ($bt === 'video' || ($video !== '' && empty($images))) {
            $bgType = 'video';
        } elseif ($bt === 'slideshow' || (!empty($s['slideshowEnabled']) && count($images) > 1)) {
            $bgType = 'slideshow';
        } elseif ($bt === 'file' && !empty($s['backgroundUrl'])) {
            $bgType = 'image';
        }
        return array_merge($defaultLoginScreen(), [
            'bgType' => $bgType,
            'videoUrl' => $video,
            'imageUrls' => $images,
            'slideshowMode' => (($s['videoPlayMode'] ?? '') === 'random') ? 'random' : 'sequential',
            'slideshowIntervalSec' => max(5, (int)($s['slideshowInterval'] ?? 18)),
        ]);
    };

    $actor = AntaraSession::user();
    $isAdmin = $actor && in_array($actor['role'] ?? '', [AntaraStore::ROLE_SUPER, AntaraStore::ROLE_ADMIN], true);

    $exportUser = static function (array $u): array {
        $role = (string)($u['role'] ?? AntaraStore::ROLE_USER);
        $legacyRole = in_array($role, [AntaraStore::ROLE_SUPER, AntaraStore::ROLE_ADMIN], true) ? 'admin' : 'user';
        return [
            'id' => (string)($u['id'] ?? ''),
            'email' => (string)($u['email'] ?? ''),
            'phone' => (string)($u['phone'] ?? ''),
            'username' => (string)($u['username'] ?? ''),
            'role' => $legacyRole,
            'createdAt' => $u['createdAt'] ?? null,
            'metadata' => array_merge(
                is_array($u['metadata'] ?? null) ? $u['metadata'] : [],
                ['serverRole' => $role, 'antaraUser' => true]
            ),
            'passwordSalt' => '',
            'passwordHash' => '',
            'pinSalt' => '',
            'pinHash' => '',
            'patternSalt' => '',
            'patternHash' => '',
            'patternSeq' => '',
            'recoverySalt' => '',
            'recoveryHash' => '',
            'webauthnCredentials' => [],
            'active' => !empty($u['active']),
            'blocked' => !empty($u['blocked']),
            'requirePasswordReset' => !empty($u['requirePasswordReset']),
            'branchId' => (string)($u['branchId'] ?? ''),
        ];
    };

    try {
        switch ($action) {
            case 'gridAuthGetAppSettings': {
                $cfg = AntaraStore::configRead();
                $s = $readSettings();
                echo json_encode([
                    'success' => true,
                    'data' => [
                        'requireLogin' => (bool)$cfg['login_required'],
                        'publicSignup' => (bool)$cfg['allow_user_registration'],
                        'publicDesktopWithoutUsers' => !empty($cfg['public_desktop_without_users']),
                        'loginScreen' => $loginScreenFromSettings($s),
                        'deploymentKind' => in_array(($s['deploymentKind'] ?? ''), ['personal', 'company'], true) ? $s['deploymentKind'] : 'personal',
                        'branches' => isset($s['branches']) && is_array($s['branches']) ? array_values(array_map(static function ($b) {
                            if (!is_array($b)) {
                                return ['id' => '', 'name' => '', 'code' => ''];
                            }
                            return [
                                'id' => (string)($b['id'] ?? ''),
                                'name' => (string)($b['name'] ?? ''),
                                'code' => (string)($b['code'] ?? ''),
                            ];
                        }, $s['branches'])) : [],
                        'defaultBranchId' => (string)($s['defaultBranchId'] ?? ''),
                        'branchAccessDefaults' => is_array($s['branchAccessDefaults'] ?? null) ? $s['branchAccessDefaults'] : [],
                    ],
                ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
                exit;
            }

            case 'gridAuthSaveAppSettings': {
                if ($method !== 'POST') {
                    echo json_encode(['success' => false, 'error' => 'Method not allowed']);
                    exit;
                }
                if (!$isAdmin) {
                    AntaraLogger::log('gridauth.save_app_settings_forbidden', []);
                    echo json_encode(['success' => false, 'error' => 'Forbidden']);
                    exit;
                }
                $input = json_decode((string)file_get_contents('php://input'), true);
                if (!is_array($input)) {
                    $input = [];
                }
                if (!antara_gridauth_csrf_or_same_site($input)) {
                    AntaraLogger::log('gridauth.save_app_settings_csrf_fail', ['user' => $actor['id'] ?? null]);
                    echo json_encode(['success' => false, 'error' => 'CSRF validation failed']);
                    exit;
                }
                $patch = [];
                if (array_key_exists('requireLogin', $input)) {
                    $patch['login_required'] = (bool)$input['requireLogin'];
                }
                if (array_key_exists('publicSignup', $input)) {
                    $patch['allow_user_registration'] = $input['publicSignup'] !== false;
                }
                if (array_key_exists('publicDesktopWithoutUsers', $input)) {
                    $patch['public_desktop_without_users'] = $input['publicDesktopWithoutUsers'] === true;
                }
                if ($patch) {
                    AntaraStore::configWrite($patch);
                }
                $cur = $readSettings();
                if (isset($input['loginScreen']) && is_array($input['loginScreen'])) {
                    $cur['loginScreen'] = array_merge($cur['loginScreen'] ?? [], $input['loginScreen']);
                    $persistSettings($cur);
                }
                $cfg = AntaraStore::configRead();
                $s = $readSettings();
                AntaraLogger::log('gridauth.app_settings_saved', [
                    'user' => $actor['id'] ?? null,
                    'keys' => array_keys($patch),
                    'loginScreen' => isset($input['loginScreen']) && is_array($input['loginScreen']),
                ]);
                echo json_encode([
                    'success' => true,
                    'data' => [
                        'requireLogin' => (bool)$cfg['login_required'],
                        'publicSignup' => (bool)$cfg['allow_user_registration'],
                        'publicDesktopWithoutUsers' => !empty($cfg['public_desktop_without_users']),
                        'loginScreen' => $loginScreenFromSettings($s),
                        'deploymentKind' => in_array(($s['deploymentKind'] ?? ''), ['personal', 'company'], true) ? $s['deploymentKind'] : 'personal',
                        'branches' => isset($s['branches']) && is_array($s['branches']) ? array_values(array_map(static function ($b) {
                            if (!is_array($b)) {
                                return ['id' => '', 'name' => '', 'code' => ''];
                            }
                            return [
                                'id' => (string)($b['id'] ?? ''),
                                'name' => (string)($b['name'] ?? ''),
                                'code' => (string)($b['code'] ?? ''),
                            ];
                        }, $s['branches'])) : [],
                        'defaultBranchId' => (string)($s['defaultBranchId'] ?? ''),
                        'branchAccessDefaults' => is_array($s['branchAccessDefaults'] ?? null) ? $s['branchAccessDefaults'] : [],
                    ],
                ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
                exit;
            }

            case 'gridAuthGetUsers': {
                if (!$isAdmin) {
                    echo json_encode(['success' => true, 'data' => ['version' => 1, 'users' => []]], JSON_UNESCAPED_UNICODE);
                    exit;
                }
                $blob = AntaraStore::usersAll();
                $out = [];
                foreach ($blob['users'] ?? [] as $u) {
                    if (!empty($u['deletedAt'])) {
                        continue;
                    }
                    $out[] = $exportUser($u);
                }
                echo json_encode(['success' => true, 'data' => ['version' => 1, 'users' => $out]], JSON_UNESCAPED_UNICODE);
                exit;
            }

            case 'gridAuthSaveUsers': {
                echo json_encode([
                    'success' => false,
                    'error' => 'User storage is server-managed. Use /admin/users/ or the auth API.',
                ], JSON_UNESCAPED_UNICODE);
                exit;
            }

            case 'gridAuthGetFolderPermissions': {
                $s = $readSettings();
                $blob = ['version' => 1, 'entries' => []];
                if (isset($s['folderPermissions']) && is_array($s['folderPermissions'])) {
                    $blob = $s['folderPermissions'];
                    if (!isset($blob['version'])) {
                        $blob['version'] = 1;
                    }
                    if (!isset($blob['entries']) || !is_array($blob['entries'])) {
                        $blob['entries'] = [];
                    }
                }
                echo json_encode(['success' => true, 'data' => $blob], JSON_UNESCAPED_UNICODE);
                exit;
            }

            case 'gridAuthSaveFolderPermissions': {
                if ($method !== 'POST') {
                    echo json_encode(['success' => false, 'error' => 'Method not allowed']);
                    exit;
                }
                if (!$isAdmin) {
                    AntaraLogger::log('gridauth.save_folder_perms_forbidden', []);
                    echo json_encode(['success' => false, 'error' => 'Forbidden']);
                    exit;
                }
                $input = json_decode((string)file_get_contents('php://input'), true);
                if (!is_array($input)) {
                    echo json_encode(['success' => false, 'error' => 'Invalid JSON']);
                    exit;
                }
                if (!antara_gridauth_csrf_or_same_site($input)) {
                    AntaraLogger::log('gridauth.save_folder_perms_csrf_fail', ['user' => $actor['id'] ?? null]);
                    echo json_encode(['success' => false, 'error' => 'CSRF validation failed']);
                    exit;
                }
                $cur = $readSettings();
                $cur['folderPermissions'] = [
                    'version' => (int)($input['version'] ?? 1),
                    'entries' => is_array($input['entries'] ?? null) ? $input['entries'] : [],
                ];
                $persistSettings($cur);
                AntaraLogger::log('gridauth.folder_permissions_saved', [
                    'user' => $actor['id'] ?? null,
                    'entries' => count($cur['folderPermissions']['entries'] ?? []),
                ]);
                echo json_encode(['success' => true, 'data' => $cur['folderPermissions']], JSON_UNESCAPED_UNICODE);
                exit;
            }

            case 'gridAuthWebAuthnBegin':
            case 'gridAuthWebAuthnFinish':
                echo json_encode([
                    'success' => false,
                    'error' => 'Legacy WebAuthn bridge removed. Use /login/ or core/auth/api.php (webauthn* actions).',
                ], JSON_UNESCAPED_UNICODE);
                exit;

            default:
                echo json_encode(['success' => false, 'error' => 'Unknown gridAuth action'], JSON_UNESCAPED_UNICODE);
                exit;
        }
    } catch (\Throwable $e) {
        if (class_exists('AntaraLogger')) {
            AntaraLogger::log('gridauth.exception', ['action' => $action, 'error' => $e->getMessage()]);
        }
        echo json_encode(['success' => false, 'error' => 'Internal error'], JSON_UNESCAPED_UNICODE);
        exit;
    }
}
