<?php
/**
 * Settings Management Class
 *
 * @package ResponsiveMobileSelect\Core
 * @since 2.0.0
 */

namespace ResponsiveMobileSelect\Core;

// Direktzugriff verhindern.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Verwaltet das Laden, Validieren und Speichern der Plugin-Einstellungen.
 * Strikt „per Blog“: Es werden nur Blog-Optionen verwendet.
 */
class Settings {

	/**
	 * Optionsname in wp_options (pro Blog).
	 */
	const OPTION_NAME = 'rms_plugin_settings_v2';

	/**
	 * Aktuelle Settings (assoziatives Array).
	 *
	 * @var array
	 */
	protected $settings = array();

	/**
	 * Default-Werte (werden bei fehlenden Keys gemerged).
	 *
	 * @var array
	 */
	protected $defaults = array(
		'max_width'           => 960,
		'menu_locations'      => array(),
		'menu_ids'            => array(),
		'activate_all'        => '0',
		'activate_all_ids'    => '0',
		'placeholder_text'    => 'Navigate',
		'indent_character'    => '— ',
		'exclude_empty_links' => '0',
		'highlight_current'   => '0',
		'max_depth'           => 0,
	);

	/**
	 * Konstruktor: lädt aktuelle Settings (mit Defaults).
	 */
	public function __construct() {
		$stored = get_option( self::OPTION_NAME, array() );
		if ( ! is_array( $stored ) ) {
			$stored = array();
		}
		$this->settings = $this->merge_defaults( $stored );
	}

	/**
	 * Liefert aktuelle Settings (Array).
	 *
	 * @return array
	 */
	public function all() {
		return $this->settings;
	}

	/**
	 * Einzelnen Wert holen (mit Default-Fallback).
	 *
	 * @param string $key Key.
	 * @return mixed
	 */
	public function get( $key ) {
		$all = $this->settings;
		return array_key_exists( $key, $all ) ? $all[ $key ] : ( $this->defaults[ $key ] ?? null );
	}

	/**
	 * Einzelnen Wert setzen (ohne Persistenz).
	 *
	 * @param string $key   Key.
	 * @param mixed  $value Wert.
	 */
	public function set( $key, $value ) {
		$this->settings[ $key ] = $value;
	}

	/**
	 * Settings speichern (stabil via update_option).
	 * – Kein delete+add (vermeidet Cache-/Race-Conditions).
	 * – Legt Option an, falls sie nicht existiert (autoload=no).
	 *
	 * @return bool Erfolg.
	 */
	public function save() {
		$to_save = $this->merge_defaults( $this->settings );

		if ( false === get_option( self::OPTION_NAME, false ) ) {
			return (bool) add_option( self::OPTION_NAME, $to_save, '', 'no' );
		}
		return (bool) update_option( self::OPTION_NAME, $to_save );
	}

	/**
	 * Formdaten validieren/säubern und in $this->settings übernehmen.
	 * (Wird z.B. vom Admin-AJAX-Handler aufgerufen.)
	 *
	 * @param array $input Rohdaten (z.B. $_POST).
	 * @return array Gesäuberte Settings (auch intern gesetzt).
	 */
	public function update_from_form( $input ) {
		$input = is_array( $input ) ? $input : array();

		$out = $this->defaults;

		// Integers.
		$out['max_width'] = isset( $input['max_width'] ) ? max( 0, absint( $input['max_width'] ) ) : $this->defaults['max_width'];
		$out['max_depth'] = isset( $input['max_depth'] ) ? max( 0, absint( $input['max_depth'] ) ) : $this->defaults['max_depth'];

		// Checkboxes (Strings '1'/'0' für einfache Template-Checks).
		$out['activate_all']        = empty( $input['activate_all'] )        ? '0' : '1';
		$out['activate_all_ids']    = empty( $input['activate_all_ids'] )    ? '0' : '1';
		$out['exclude_empty_links'] = empty( $input['exclude_empty_links'] ) ? '0' : '1';
		$out['highlight_current']   = empty( $input['highlight_current'] )   ? '0' : '1';

		// Strings.
		$out['placeholder_text'] = isset( $input['placeholder_text'] ) ? sanitize_text_field( $input['placeholder_text'] ) : $this->defaults['placeholder_text'];
		$out['indent_character'] = isset( $input['indent_character'] ) ? sanitize_text_field( $input['indent_character'] ) : $this->defaults['indent_character'];

		// Arrays.
		$out['menu_locations'] = array_values(
			array_filter(
				array_map( 'sanitize_key', isset( $input['menu_locations'] ) && is_array( $input['menu_locations'] ) ? $input['menu_locations'] : array() )
			)
		);
		$out['menu_ids'] = array_values(
			array_filter(
				array_map( 'absint', isset( $input['menu_ids'] ) && is_array( $input['menu_ids'] ) ? $input['menu_ids'] : array() )
			)
		);

		$this->settings = $out;
		return $this->settings;
	}

	/**
	 * Reset auf Defaults (ohne persistentes Speichern).
	 *
	 * @return bool Immer true (Kompatibilität).
	 */
	public function reset_to_defaults() {
		$this->settings = $this->defaults;
		return true;
	}

	/**
	 * Defaults in Array mergen.
	 *
	 * @param array $arr Eingabe.
	 * @return array Ausgabe (mit allen Keys vorhanden).
	 */
	protected function merge_defaults( $arr ) {
		$arr   = is_array( $arr ) ? $arr : array();
		$merged = wp_parse_args( $arr, $this->defaults );

		// Nach-Merge: leichte Rekonstruktion von Typen.
		$merged['max_width'] = max( 0, absint( $merged['max_width'] ) );
		$merged['max_depth'] = max( 0, absint( $merged['max_depth'] ) );

		$merged['activate_all']        = empty( $merged['activate_all'] )        ? '0' : '1';
		$merged['activate_all_ids']    = empty( $merged['activate_all_ids'] )    ? '0' : '1';
		$merged['exclude_empty_links'] = empty( $merged['exclude_empty_links'] ) ? '0' : '1';
		$merged['highlight_current']   = empty( $merged['highlight_current'] )   ? '0' : '1';

		$merged['placeholder_text'] = sanitize_text_field( $merged['placeholder_text'] );
		$merged['indent_character'] = sanitize_text_field( $merged['indent_character'] );

		$merged['menu_locations'] = array_values( array_filter( array_map( 'sanitize_key', (array) $merged['menu_locations'] ) ) );
		$merged['menu_ids']       = array_values( array_filter( array_map( 'absint',      (array) $merged['menu_ids'] ) ) );

		return $merged;
	}
}
