<?php

/**
 * User Preferences Service
 *
 * Manages user-specific preferences stored in user meta.
 *
 * @package ProRank\SEO\Core
 * @since   0.1.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Core;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}


/**
 * User Preferences class
 */


class UserPreferences {
    
    /**
     * Meta key prefix for user preferences
     *
     * @var string
     */
    private const META_PREFIX = '_prorank_';
    
    /**
     * Expert mode meta key
     *
     * @var string
     */
    public const EXPERT_MODE_KEY = self::META_PREFIX . 'expert_mode';
    
    /**
     * Pinned modules meta key
     *
     * @var string
     */
    public const PINNED_MODULES_KEY = self::META_PREFIX . 'pinned_modules';
    
    /**
     * Get user preference value
     *
     * @param string $key     Preference key
     * @param mixed  $default Default value if not set
     * @param int    $user_id User ID (defaults to current user)
     * @return mixed Preference value
     */
    public static function get(string $key, $default = null, int $user_id = 0) {
        if (!$user_id) {
            $user_id = get_current_user_id();
        }
        
        if (!$user_id) {
            return $default;
        }
        
        $value = get_user_meta($user_id, $key, true);
        
        return $value !== '' ? $value : $default;
    }
    
    /**
     * Set user preference value
     *
     * @param string $key     Preference key
     * @param mixed  $value   Preference value
     * @param int    $user_id User ID (defaults to current user)
     * @return bool True on success, false on failure
     */
    public static function set(string $key, $value, int $user_id = 0): bool {
        if (!$user_id) {
            $user_id = get_current_user_id();
        }
        
        if (!$user_id) {
            return false;
        }
        
        // Check capability
        if (!user_can($user_id, 'edit_posts')) {
            return false;
        }
        
        return (bool) update_user_meta($user_id, $key, $value);
    }
    
    /**
     * Delete user preference
     *
     * @param string $key     Preference key
     * @param int    $user_id User ID (defaults to current user)
     * @return bool True on success, false on failure
     */
    public static function delete(string $key, int $user_id = 0): bool {
        if (!$user_id) {
            $user_id = get_current_user_id();
        }
        
        if (!$user_id) {
            return false;
        }
        
        return delete_user_meta($user_id, $key);
    }
    
    /**
     * Check if expert mode is enabled for user
     *
     * @param int $user_id User ID (defaults to current user)
     * @return bool True if expert mode is enabled
     */
    public static function is_expert_mode(int $user_id = 0): bool {
        return (bool) self::get(self::EXPERT_MODE_KEY, false, $user_id);
    }
    
    /**
     * Set expert mode status for user
     *
     * @param bool $enabled  Enable or disable expert mode
     * @param int  $user_id User ID (defaults to current user)
     * @return bool True on success
     */
    public static function set_expert_mode(bool $enabled, int $user_id = 0): bool {
        return self::set(self::EXPERT_MODE_KEY, $enabled, $user_id);
    }
    
    /**
     * Get pinned modules for user
     *
     * @param int $user_id User ID (defaults to current user)
     * @return array Array of pinned module slugs
     */
    public static function get_pinned_modules(int $user_id = 0): array {
        $pinned = self::get(self::PINNED_MODULES_KEY, [], $user_id);
        
        if (!is_array($pinned)) {
            return [];
        }
        
        // Sanitize module slugs
        return array_map('sanitize_key', $pinned);
    }
    
    /**
     * Set pinned modules for user
     *
     * @param array $modules Array of module slugs to pin
     * @param int   $user_id User ID (defaults to current user)
     * @return bool True on success
     */
    public static function set_pinned_modules(array $modules, int $user_id = 0): bool {
        // Sanitize module slugs
        $modules = array_map('sanitize_key', $modules);
        $modules = array_unique($modules);
        $modules = array_values($modules); // Re-index array
        
        return self::set(self::PINNED_MODULES_KEY, $modules, $user_id);
    }
    
    /**
     * Toggle a module's pinned status
     *
     * @param string $module_slug Module slug
     * @param int    $user_id     User ID (defaults to current user)
     * @return bool True if now pinned, false if unpinned
     */
    public static function toggle_pinned_module(string $module_slug, int $user_id = 0): bool {
        $module_slug = sanitize_key($module_slug);
        $pinned = self::get_pinned_modules($user_id);
        
        $key = array_search($module_slug, $pinned, true);
        
        if ($key !== false) {
            // Remove from pinned
            unset($pinned[$key]);
            $is_pinned = false;
        } else {
            // Add to pinned
            $pinned[] = $module_slug;
            $is_pinned = true;
        }
        
        self::set_pinned_modules(array_values($pinned), $user_id);
        
        return $is_pinned;
    }
    
    /**
     * Get all preferences for a user
     *
     * @param int $user_id User ID (defaults to current user)
     * @return array Array of all preferences
     */
    public static function get_all(int $user_id = 0): array {
        if (!$user_id) {
            $user_id = get_current_user_id();
        }
        
        if (!$user_id) {
            return [];
        }
        
        global $wpdb;
        
        // Get all user meta with our prefix
        $results = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT meta_key, meta_value 
                FROM {$wpdb->usermeta} 
                WHERE user_id = %d 
                AND meta_key LIKE %s",
                $user_id,
                $wpdb->esc_like(self::META_PREFIX) . '%'
            ),
            ARRAY_A
        );
        
        $preferences = [];
        
        if ($results) {
            foreach ($results as $row) {
                $key = str_replace(self::META_PREFIX, '', $row['meta_key']);
                $preferences[$key] = maybe_unserialize($row['meta_value']);
            }
        }
        
        return $preferences;
    }
}