<?php
declare(strict_types=1);


/**
 * Settings Manager
 *
 * @package ProRank\Core
 */

namespace ProRank\SEO\Core;

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


/**
 * Manages plugin settings
 */


class SettingsManager {
    
    /**
     * Settings option name
     *
     * @var string
     */
    private const OPTION_NAME = 'prorank_settings';
    
    /**
     * Settings cache
     *
     * @var array|null
     */
    private ?array $settings = null;
    
    /**
     * Registered settings schema
     *
     * @var array
     */
    private array $registered_settings = [];
    
    /**
     * Get all settings
     *
     * @return array
     */
    public function get_all(): array {
        if ( null === $this->settings ) {
            $this->settings = get_option( self::OPTION_NAME, [] );
        }
        
        return $this->settings;
    }
    
    /**
     * Get a specific setting
     *
     * @param string $key_or_group Setting key or group name
     * @param mixed $key_or_default Setting key (if first param is group) or default value
     * @param mixed $default Default value (only used if first param is group)
     * @return mixed
     */
    public function get( string $key_or_group, $key_or_default = null, $default = null ) {
        // Check if we're using the 3-parameter version (group, key, default)
        if ( func_num_args() === 3 ) {
            $group = $key_or_group;
            $key = $key_or_default;
            $namespaced_key = $group . '_' . $key;
            $settings = $this->get_all();
            return $settings[ $namespaced_key ] ?? $default;
        }
        
        // Otherwise, use the 2-parameter version (key, default)
        $settings = $this->get_all();
        return $settings[ $key_or_group ] ?? $key_or_default;
    }
    
    /**
     * Update a setting
     *
     * @param string $key Setting key
     * @param mixed $value Setting value
     * @param string|null $group Optional setting group for namespaced keys.
     * @return bool
     */
    public function update( string $key, $value, ?string $group = null ): bool {
        if ( $group !== null && $group !== '' && strpos( $key, $group . '_' ) !== 0 ) {
            $key = $group . '_' . $key;
        }

        $settings = $this->get_all();
        $settings[ $key ] = $value;
        $this->settings = $settings;
        
        return update_option( self::OPTION_NAME, $settings );
    }
    
    /**
     * Get settings for a specific group
     *
     * @param string $group Group name
     * @return array
     */
    public function get_settings( string $group ): array {
        // Return all settings prefixed with the group name, but strip the prefix
        $all_settings = $this->get_all();
        $group_settings = [];
        $prefix = $group . '_';
        $prefix_len = strlen($prefix);
        
        foreach ( $all_settings as $key => $value ) {
            if ( strpos( $key, $prefix ) === 0 ) {
                // Strip the prefix so frontend gets unprefixed keys
                $unprefixed_key = substr($key, $prefix_len);
                $group_settings[ $unprefixed_key ] = $value;
            }
        }
        
        return $group_settings;
    }
    
    /**
     * Update a setting within a group
     *
     * @param string $group Group name
     * @param string $key Setting key
     * @param mixed $value Setting value
     * @return bool
     */
    public function update_setting( string $group, string $key, $value ): bool {
        // Create a namespaced key
        $namespaced_key = $group . '_' . $key;
        return $this->update( $namespaced_key, $value );
    }
    
    /**
     * Register setting group
     *
     * @param string $group Group name
     * @param array $defaults Default values
     */
    public function register_group( string $group, array $defaults ): void {
        // Implementation for registering setting groups
    }
    
    /**
     * Update multiple settings for a group
     *
     * @param string $group Group name
     * @param array $settings Settings to update
     * @return bool
     */
    public function update_settings_group( string $group, array $settings ): bool {
        $all_settings = $this->get_all();
        $updated = false;
        
        foreach ( $settings as $key => $value ) {
            // If key doesn't already have the group prefix, add it
            if ( strpos( $key, $group . '_' ) !== 0 ) {
                $key = $group . '_' . $key;
            }
            
            $all_settings[ $key ] = $value;
            $updated = true;
        }
        
        if ( $updated ) {
            $this->settings = $all_settings;
            return update_option( self::OPTION_NAME, $all_settings );
        }
        
        return false;
    }
    
    /**
     * Get registered settings for a group
     *
     * @param string $group Group name
     * @return array
     */
    public function get_registered_settings( string $group ): array {
        return $this->registered_settings[ $group ] ?? [];
    }
    
    /**
     * Register settings schema for a group
     *
     * @param string $group Group name
     * @param array $schema Settings schema
     * @return void
     */
    public function register_settings_schema( string $group, array $schema ): void {
        $this->registered_settings[ $group ] = $schema;
    }
}
