<?php
/**
 * Perfiles de usuario: settings personales, carpetas de explorador y merge con workspace.
 */

require_once __DIR__ . '/grid_default_settings.php';
require_once __DIR__ . '/settings_helpers.php';

if (!function_exists('grid_user_settings_keys')) {
    /**
     * Claves que pertenecen al perfil personal de cada usuario (no al workspace global).
     *
     * @return list<string>
     */
    function grid_user_settings_keys(): array
    {
        return [
            'backgroundType', 'backgroundUrl', 'backgroundImages', 'backgroundVideos',
            'videoPlayMode', 'slideshowEnabled', 'slideshowInterval',
            'youtubeBackground', 'youtubeBackgroundMobile', 'youtubePlaylistPC', 'youtubePlaylistMobile',
            'usePlaylist', 'youtubePlayMode',
            'mosaicColor', 'selectedTheme', 'selectedFont', 'selectedFontSize',
            'textColor', 'gridTextColor', 'gradientColor1', 'gradientColor2',
            'categories', 'apps', 'desktopMode', 'showTypeBadge', 'typeBadgeMode', 'inspectBlock',
            'startButtonIcon', 'recycleBin', 'taskbarPosition', 'pinnedApps', 'taskbarOpenOrder',
            'fileExplorerTrash', 'fileExplorerConnections',
            'mobileDesktopMode', 'pageZoom', 'iframeZoom', 'desktopShortcuts', 'appLocale',
            'openWindowsSessionShared', 'launcherLayout', 'quickNotes', 'mediaWidgetItems', 'osWidgetOrder',
        ];
    }
}

if (!function_exists('grid_user_settings_session_user_id')) {
    function grid_user_settings_session_user_id(): ?string
    {
        if (!class_exists('AntaraSession', false)) {
            return null;
        }
        if (!AntaraSession::isLoggedIn()) {
            return null;
        }
        $u = AntaraSession::user();
        $id = is_array($u) ? trim((string) ($u['id'] ?? '')) : '';
        if ($id === '') {
            return null;
        }
        if (!function_exists('antara_user_profile_is_uuid')) {
            require_once dirname(__DIR__) . '/core/auth/profile_image_ops.php';
        }
        if (!antara_user_profile_is_uuid($id)) {
            return null;
        }

        return $id;
    }
}

if (!function_exists('grid_user_settings_can_write_workspace')) {
    function grid_user_settings_can_write_workspace(): bool
    {
        $uid = grid_user_settings_session_user_id();
        if ($uid === null) {
            return true;
        }
        if (!class_exists('AntaraStore', false)) {
            require_once dirname(__DIR__) . '/core/auth/store.php';
        }
        $fresh = AntaraStore::findUserById($uid);
        if (!$fresh) {
            return false;
        }

        return in_array($fresh['role'] ?? '', [AntaraStore::ROLE_SUPER, AntaraStore::ROLE_ADMIN], true);
    }
}

if (!function_exists('grid_user_profile_dir')) {
    function grid_user_profile_dir(string $userId): string
    {
        if (!function_exists('antara_user_profile_is_uuid')) {
            require_once dirname(__DIR__) . '/core/auth/profile_image_ops.php';
        }
        if (!antara_user_profile_is_uuid($userId)) {
            throw new InvalidArgumentException('Invalid user id');
        }
        $root = defined('GRID_ROOT') && is_string(GRID_ROOT) && GRID_ROOT !== ''
            ? GRID_ROOT
            : dirname(__DIR__);

        return $root . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . 'users' . DIRECTORY_SEPARATOR . $userId;
    }
}

if (!function_exists('grid_user_settings_file')) {
    function grid_user_settings_file(string $userId): string
    {
        return grid_user_profile_dir($userId) . DIRECTORY_SEPARATOR . 'settings.json';
    }
}

if (!function_exists('grid_user_settings_backup_file')) {
    function grid_user_settings_backup_file(string $userId): string
    {
        return grid_user_profile_dir($userId) . DIRECTORY_SEPARATOR . 'settings.json.bak';
    }
}

if (!function_exists('grid_user_ensure_profile_dir')) {
    function grid_user_ensure_profile_dir(string $userId): bool
    {
        $dir = grid_user_profile_dir($userId);
        if (is_dir($dir)) {
            return true;
        }

        return @mkdir($dir, 0700, true) || is_dir($dir);
    }
}

if (!function_exists('grid_user_settings_defaults')) {
    /**
     * @return array<string, mixed>
     */
    function grid_user_settings_defaults(): array
    {
        $all = grid_app_default_settings();
        $keys = grid_user_settings_keys();
        $out = [];
        foreach ($keys as $k) {
            if (array_key_exists($k, $all)) {
                $out[$k] = $all[$k];
            }
        }

        return $out;
    }
}

if (!function_exists('grid_user_settings_pick')) {
    /**
     * @param array<string, mixed> $source
     * @return array<string, mixed>
     */
    function grid_user_settings_pick(array $source): array
    {
        $out = [];
        foreach (grid_user_settings_keys() as $k) {
            if (array_key_exists($k, $source)) {
                $out[$k] = $source[$k];
            }
        }

        return $out;
    }
}

if (!function_exists('grid_user_settings_omit')) {
    /**
     * @param array<string, mixed> $source
     * @return array<string, mixed>
     */
    function grid_user_settings_omit(array $source): array
    {
        $omit = array_fill_keys(grid_user_settings_keys(), true);
        $out = [];
        foreach ($source as $k => $v) {
            if (!isset($omit[$k])) {
                $out[$k] = $v;
            }
        }

        return $out;
    }
}

if (!function_exists('grid_user_settings_split_patch')) {
    /**
     * @param array<string, mixed> $patch
     * @return array{0: array<string, mixed>, 1: array<string, mixed>}
     */
    function grid_user_settings_split_patch(array $patch): array
    {
        $user = [];
        $workspace = [];
        $userKeys = array_fill_keys(grid_user_settings_keys(), true);
        foreach ($patch as $k => $v) {
            if (isset($userKeys[$k])) {
                $user[$k] = $v;
            } else {
                $workspace[$k] = $v;
            }
        }

        return [$user, $workspace];
    }
}

if (!function_exists('grid_user_settings_read_raw')) {
    /**
     * @return array<string, mixed>|null
     */
    function grid_user_settings_read_raw(string $userId): ?array
    {
        $path = grid_user_settings_file($userId);
        if (!is_file($path)) {
            return null;
        }
        $raw = @file_get_contents($path);
        if ($raw === false || $raw === '') {
            return null;
        }
        $data = grid_decode_settings_json($raw);
        if (!is_array($data)) {
            return null;
        }

        return $data;
    }
}

if (!function_exists('grid_user_settings_bootstrap')) {
    /**
     * Crea el perfil del usuario copiando claves personales del workspace (migración legacy).
     *
     * @param array<string, mixed> $workspaceSettings
     * @return array<string, mixed>
     */
    function grid_user_settings_bootstrap(string $userId, array $workspaceSettings): array
    {
        grid_user_ensure_profile_dir($userId);
        $defaults = grid_user_settings_defaults();
        $legacy = grid_user_settings_pick($workspaceSettings);
        $profile = array_merge($defaults, $legacy);
        $profile['osWidgetOrder'] = grid_normalize_os_widget_order($defaults['osWidgetOrder'] ?? null);
        $profile['userId'] = $userId;
        $profile['profileVersion'] = 1;
        $profile['createdAt'] = gmdate('Y-m-d\TH:i:s\Z');
        $profile['updatedAt'] = $profile['createdAt'];
        grid_user_settings_persist($userId, $profile);
        grid_user_ensure_explorer_dirs($userId);

        return grid_user_settings_pick($profile);
    }
}

if (!function_exists('grid_user_settings_read')) {
    /**
     * @param array<string, mixed> $workspaceSettings
     * @return array<string, mixed>
     */
    function grid_user_settings_read(string $userId, array $workspaceSettings): array
    {
        $raw = grid_user_settings_read_raw($userId);
        if ($raw === null) {
            return grid_user_settings_bootstrap($userId, $workspaceSettings);
        }
        $defaults = grid_user_settings_defaults();
        $merged = array_merge($defaults, grid_user_settings_pick($raw));
        $prevOrder = $merged['osWidgetOrder'] ?? null;
        $merged['osWidgetOrder'] = grid_normalize_os_widget_order($prevOrder);
        if ($prevOrder !== $merged['osWidgetOrder']) {
            grid_user_settings_persist($userId, $merged);
        }

        return $merged;
    }
}

if (!function_exists('grid_user_settings_persist')) {
    function grid_user_settings_persist(string $userId, array $profile): bool
    {
        grid_user_ensure_profile_dir($userId);
        $path = grid_user_settings_file($userId);
        $backup = grid_user_settings_backup_file($userId);
        $payload = grid_user_settings_pick($profile);
        $payload['userId'] = $userId;
        $payload['profileVersion'] = (int) ($profile['profileVersion'] ?? 1);
        $payload['updatedAt'] = gmdate('Y-m-d\TH:i:s\Z');
        if (!isset($payload['createdAt']) || !is_string($payload['createdAt'])) {
            $existing = grid_user_settings_read_raw($userId);
            $payload['createdAt'] = is_array($existing) && !empty($existing['createdAt'])
                ? (string) $existing['createdAt']
                : $payload['updatedAt'];
        }

        return grid_persist_settings($path, $backup, $payload);
    }
}

if (!function_exists('grid_settings_merged_for_user')) {
    /**
     * Workspace global + perfil personal del usuario.
     *
     * @param array<string, mixed> $workspaceSettings
     * @return array<string, mixed>
     */
    function grid_settings_merged_for_user(array $workspaceSettings, string $userId): array
    {
        $workspace = grid_user_settings_omit($workspaceSettings);
        $userProfile = grid_user_settings_read($userId, $workspaceSettings);

        return array_merge($workspace, $userProfile);
    }
}

if (!function_exists('grid_settings_merged_for_session')) {
    /**
     * @param array<string, mixed> $workspaceSettings
     * @return array<string, mixed>
     */
    function grid_settings_merged_for_session(array $workspaceSettings): array
    {
        $uid = grid_user_settings_session_user_id();
        if ($uid === null) {
            return $workspaceSettings;
        }

        return grid_settings_merged_for_user($workspaceSettings, $uid);
    }
}

if (!function_exists('grid_user_explorer_files_dir')) {
    function grid_user_explorer_files_dir(string $userId): string
    {
        $root = defined('GRID_ROOT') && is_string(GRID_ROOT) && GRID_ROOT !== ''
            ? GRID_ROOT
            : dirname(__DIR__);

        return $root . DIRECTORY_SEPARATOR . 'media' . DIRECTORY_SEPARATOR . 'explorer'
            . DIRECTORY_SEPARATOR . 'users' . DIRECTORY_SEPARATOR . $userId
            . DIRECTORY_SEPARATOR . 'files';
    }
}

if (!function_exists('grid_user_explorer_trash_dir')) {
    function grid_user_explorer_trash_dir(string $userId): string
    {
        $root = defined('GRID_ROOT') && is_string(GRID_ROOT) && GRID_ROOT !== ''
            ? GRID_ROOT
            : dirname(__DIR__);

        return $root . DIRECTORY_SEPARATOR . 'media' . DIRECTORY_SEPARATOR . 'explorer'
            . DIRECTORY_SEPARATOR . 'users' . DIRECTORY_SEPARATOR . $userId
            . DIRECTORY_SEPARATOR . 'trash';
    }
}

if (!function_exists('grid_user_ensure_explorer_dirs')) {
    function grid_user_ensure_explorer_dirs(string $userId): void
    {
        foreach ([grid_user_explorer_files_dir($userId), grid_user_explorer_trash_dir($userId)] as $dir) {
            if (!is_dir($dir)) {
                @mkdir($dir, 0755, true);
            }
        }
    }
}

if (!function_exists('grid_explorer_session_user_id')) {
    function grid_explorer_session_user_id(): ?string
    {
        return grid_user_settings_session_user_id();
    }
}

if (!function_exists('grid_explorer_local_files_base')) {
    function grid_explorer_local_files_base(): string
    {
        $uid = grid_explorer_session_user_id();
        if ($uid !== null) {
            grid_user_ensure_explorer_dirs($uid);

            return grid_user_explorer_files_dir($uid);
        }

        return GRID_ROOT . '/media/explorer/files';
    }
}

if (!function_exists('grid_explorer_local_trash_base')) {
    function grid_explorer_local_trash_base(): string
    {
        $uid = grid_explorer_session_user_id();
        if ($uid !== null) {
            grid_user_ensure_explorer_dirs($uid);

            return grid_user_explorer_trash_dir($uid);
        }

        return GRID_ROOT . '/media/explorer/trash';
    }
}

if (!function_exists('grid_explorer_local_base_dir')) {
    function grid_explorer_local_base_dir($bucket): string
    {
        $b = (string) $bucket;
        if ($b === 'cache') {
            return GRID_ROOT . '/media/explorer/remote-cache';
        }
        if ($b === 'trash') {
            return grid_explorer_local_trash_base();
        }

        return grid_explorer_local_files_base();
    }
}

if (!function_exists('grid_explorer_local_url_prefix')) {
    /**
     * Prefijo URL web para archivos locales del bucket files/trash del usuario actual.
     */
    function grid_explorer_local_url_prefix(string $bucket): string
    {
        $uid = grid_explorer_session_user_id();
        if ($uid !== null && ($bucket === 'files' || $bucket === 'trash')) {
            $sub = $bucket === 'trash' ? 'trash' : 'files';

            return 'media/explorer/users/' . rawurlencode($uid) . '/' . $sub . '/';
        }
        if ($bucket === 'trash') {
            return 'media/explorer/trash/';
        }

        return 'media/explorer/files/';
    }
}

if (!function_exists('grid_user_settings_save_patch')) {
    /**
     * Guarda un patch repartido entre perfil de usuario y workspace.
     *
     * @param array<string, mixed> $workspaceSettings settings.json actual
     * @param array<string, mixed> $patch
     * @return array{success: bool, data?: array<string, mixed>, error?: string, code?: string}
     */
    function grid_user_settings_save_patch(array $workspaceSettings, array $patch): array
    {
        $uid = grid_user_settings_session_user_id();
        if ($uid === null) {
            $merged = array_merge($workspaceSettings, $patch);
            if (!isset($merged['categories']) || empty($merged['categories'])) {
                $merged['categories'] = ['General'];
            }
            $root = defined('GRID_ROOT') ? GRID_ROOT : dirname(__DIR__);
            $sf = $root . DIRECTORY_SEPARATOR . 'settings.json';
            $bk = $root . DIRECTORY_SEPARATOR . 'settings.json.bak';
            if (!grid_persist_settings($sf, $bk, $merged)) {
                return ['success' => false, 'error' => 'persist_failed', 'code' => 'PERSIST_FAILED'];
            }

            return ['success' => true, 'data' => $merged];
        }

        [$userPatch, $workspacePatch] = grid_user_settings_split_patch($patch);

        if ($workspacePatch !== [] && !grid_user_settings_can_write_workspace()) {
            return [
                'success' => false,
                'error' => 'No tienes permiso para modificar la configuración global del workspace.',
                'code' => 'WORKSPACE_FORBIDDEN',
            ];
        }

        if ($userPatch !== []) {
            $currentUser = grid_user_settings_read($uid, $workspaceSettings);
            $userMerged = array_merge($currentUser, $userPatch);
            if (isset($userPatch['categories']) && empty($userMerged['categories'])) {
                $userMerged['categories'] = ['General'];
            }
            if (!grid_user_settings_persist($uid, $userMerged)) {
                return ['success' => false, 'error' => 'user_persist_failed', 'code' => 'USER_PERSIST_FAILED'];
            }
        }

        $workspaceCurrent = grid_user_settings_omit($workspaceSettings);
        if ($workspacePatch !== []) {
            $workspaceMerged = array_merge($workspaceCurrent, $workspacePatch);
            $root = defined('GRID_ROOT') ? GRID_ROOT : dirname(__DIR__);
            $sf = $root . DIRECTORY_SEPARATOR . 'settings.json';
            $bk = $root . DIRECTORY_SEPARATOR . 'settings.json.bak';
            if (!grid_persist_settings($sf, $bk, $workspaceMerged)) {
                return ['success' => false, 'error' => 'workspace_persist_failed', 'code' => 'WORKSPACE_PERSIST_FAILED'];
            }
            $workspaceCurrent = $workspaceMerged;
        }

        return [
            'success' => true,
            'data' => grid_settings_merged_for_user($workspaceCurrent, $uid),
        ];
    }
}

if (!function_exists('grid_runtime_settings_read')) {
    /**
     * Settings efectivos para la sesión actual (workspace + perfil de usuario).
     *
     * @return array<string, mixed>
     */
    function grid_runtime_settings_read(string $settingsFile, string $settingsBackupFile, array $defaultSettings): array
    {
        $workspace = grid_read_settings_for_api($settingsFile, $settingsBackupFile, $defaultSettings);

        return grid_settings_merged_for_session($workspace);
    }
}

if (!function_exists('grid_runtime_settings_save_patch')) {
    function grid_runtime_settings_save_patch(string $settingsFile, string $settingsBackupFile, array $defaultSettings, array $patch): bool
    {
        $workspace = grid_read_settings_for_api($settingsFile, $settingsBackupFile, $defaultSettings);
        $result = grid_user_settings_save_patch($workspace, $patch);

        return !empty($result['success']);
    }
}

if (!function_exists('grid_user_profiles_prepare_hosting_layout')) {
    /**
     * Carpetas y protección HTTP para perfiles (instalador / bootstrap).
     */
    function grid_user_profiles_prepare_hosting_layout(): void
    {
        if (!defined('GRID_ROOT')) {
            define('GRID_ROOT', defined('ANTARA_ROOT') ? ANTARA_ROOT : dirname(__DIR__));
        }
        $root = GRID_ROOT;
        $ds = DIRECTORY_SEPARATOR;
        foreach ([
            $root . $ds . 'storage' . $ds . 'users',
            $root . $ds . 'media' . $ds . 'explorer' . $ds . 'users',
        ] as $dir) {
            if (!is_dir($dir)) {
                @mkdir($dir, is_dir($root . $ds . 'storage' . $ds . 'users') ? 0700 : 0755, true);
            }
        }
        $htUsers = $root . $ds . 'storage' . $ds . 'users' . $ds . '.htaccess';
        if (!is_file($htUsers)) {
            @file_put_contents($htUsers, "Require all denied\n");
        }
        $idxUsers = $root . $ds . 'storage' . $ds . 'users' . $ds . 'index.php';
        if (!is_file($idxUsers)) {
            @file_put_contents($idxUsers, "<?php\nheader('HTTP/1.1 403 Forbidden');\nexit;\n");
        }
    }
}

if (!function_exists('grid_user_profiles_wipe_all')) {
    /** Elimina todos los perfiles de usuario (reinstalación / formateo). */
    function grid_user_profiles_wipe_all(): void
    {
        if (!defined('GRID_ROOT')) {
            define('GRID_ROOT', defined('ANTARA_ROOT') ? ANTARA_ROOT : dirname(__DIR__));
        }
        require_once GRID_ROOT . '/includes/install_checks.php';
        $root = GRID_ROOT;
        $ds = DIRECTORY_SEPARATOR;
        $profilesRoot = $root . $ds . 'storage' . $ds . 'users';
        if (is_dir($profilesRoot)) {
            $items = @scandir($profilesRoot);
            if (is_array($items)) {
                foreach ($items as $it) {
                    if ($it === '.' || $it === '..' || $it === '.htaccess' || $it === 'index.php') {
                        continue;
                    }
                    antara_fs_remove_recursive($profilesRoot . $ds . $it);
                }
            }
        }
        $explorerUsers = $root . $ds . 'media' . $ds . 'explorer' . $ds . 'users';
        if (is_dir($explorerUsers)) {
            antara_fs_remove_recursive($explorerUsers);
            @mkdir($explorerUsers, 0755, true);
        }
    }
}

if (!function_exists('grid_install_bootstrap_user_profiles')) {
    /**
     * Crea el perfil inicial de cada cuenta al terminar la instalación.
     *
     * @param list<string> $userIds
     * @param array<string, mixed> $workspaceSettings Workspace con defaults de fábrica (antes de omitir claves personales).
     */
    function grid_install_bootstrap_user_profiles(array $userIds, array $workspaceSettings): void
    {
        if (!function_exists('antara_user_profile_is_uuid')) {
            require_once dirname(__DIR__) . '/core/auth/profile_image_ops.php';
        }
        grid_user_profiles_prepare_hosting_layout();
        foreach ($userIds as $uid) {
            $uid = trim((string) $uid);
            if ($uid === '' || !antara_user_profile_is_uuid($uid)) {
                continue;
            }
            grid_user_settings_bootstrap($uid, $workspaceSettings);
            grid_user_ensure_explorer_dirs($uid);
        }
    }
}

if (!function_exists('grid_workspace_settings_only')) {
    /**
     * settings.json del workspace sin claves de perfil personal.
     *
     * @param array<string, mixed> $settings
     * @return array<string, mixed>
     */
    function grid_workspace_settings_only(array $settings): array
    {
        $out = grid_user_settings_omit($settings);
        if (!isset($out['categories']) || !is_array($out['categories']) || count($out['categories']) === 0) {
            $out['categories'] = ['General'];
        }
        if (!isset($out['apps']) || !is_array($out['apps'])) {
            $out['apps'] = [];
        }

        return $out;
    }
}
