<?php
/**
 * Settings section data helper/service.
 *
 * Kernel-only settings context helper.
 * Module-specific and public-app defaults must be injected through filters
 * instead of being hardcoded into the central kernel.
 *
 * @package Noesia_Smart_Waiter
 */

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

if ( ! class_exists( 'Noesia_SWA_Settings_Section_Data' ) ) {
    /**
     * Settings section data helper.
     */
    class Noesia_SWA_Settings_Section_Data {

        /**
         * Build the settings section context.
         *
         * @param array<string,mixed>|null $options Optional preloaded options.
         * @return array<string,mixed>
         */
        public function get_context( $options = null ) {
            if ( ! is_array( $options ) ) {
                $options = get_option( 'noesia_swa_options', array() );
            }

            if ( ! is_array( $options ) ) {
                $options = array();
            }

            return array(
                'options'                  => $options,
                'values'                   => wp_parse_args( $options, $this->get_defaults( $options ) ),
                'settings_panels_registry' => $this->resolve_settings_panels_registry(),
            );
        }

        /**
         * Get kernel/shared settings defaults only.
         *
         * Strict isolation note:
         * - Weather defaults belong to the Weather module.
         * - News defaults belong to the News module.
         * - Screen lock defaults belong to the Screen Lock module.
         * - Public app defaults belong to the Public/App layer.
         * - Dashboard badge/default source belongs to the responsible module.
         *
         * @param array<string,mixed> $options Optional currently saved options.
         * @return array<string,mixed>
         */
        public function get_defaults( $options = array() ) {
            $options = is_array( $options ) ? $options : array();

            $defaults = array(
                'profile_business_name'   => '',
                'profile_host_name'       => '',
                'profile_business_type'   => '',
                'profile_address'         => '',
                'profile_phone'           => '',
                'profile_email'           => '',
                'profile_website'         => '',
                'profile_tax_id'          => '',
                'profile_registration_no' => '',
                'menu_hidden_sections'    => '[]',
                'dock_shortcuts_v1'      => '[]',
            );

            for ( $i = 1; $i <= 8; $i++ ) {
                $defaults[ 'bookmark_' . $i . '_name' ] = '';
                $defaults[ 'bookmark_' . $i . '_url' ]  = '';
            }

            /**
             * Allow modules / public layer to inject their own defaults.
             *
             * Examples:
             * - weather_* fields
             * - news_language
             * - screensaver_* fields
             * - dashboard_stats_source / global_active_badge_type
             * - public app labels/buttons/icons
             *
             * @param array<string,mixed>              $defaults Kernel/shared defaults so far.
             * @param array<string,mixed>              $options  Existing saved options.
             * @param Noesia_SWA_Settings_Section_Data $this     Settings section data helper.
             */
            $defaults = apply_filters( 'noesia_swa_option_defaults', $defaults, $options, $this );

            if ( ! is_array( $defaults ) ) {
                $defaults = array();
            }

            return $defaults;
        }

        /**
         * Preferred settings group order.
         *
         * The kernel must not hardcode module/public group names.
         * Modules or bootstrap code may provide a preferred order through
         * filters if they need deterministic grouping.
         *
         * @return array<int,string>
         */
        public function get_preferred_groups() {
            $groups = array();

            /**
             * Filter preferred settings group order.
             *
             * Return an ordered list of group slugs if a deterministic order is
             * desired. By default the kernel stays blind and returns no opinion.
             *
             * @param array<int,string>               $groups Preferred group order.
             * @param Noesia_SWA_Settings_Section_Data $this  Settings section data helper.
             */
            $groups = apply_filters( 'noesia_swa_settings_group_order_preference', $groups, $this );

            if ( ! is_array( $groups ) ) {
                return array();
            }

            $groups = array_values(
                array_unique(
                    array_filter(
                        array_map( 'sanitize_key', $groups )
                    )
                )
            );

            return $groups;
        }

        /**
         * Build a resolved group render order.
         *
         * @param Noesia_SWA_Settings_Panels $registry Settings panels registry.
         * @return array<int,string>
         */
        public function get_group_order( $registry ) {
            if ( ! $registry instanceof Noesia_SWA_Settings_Panels ) {
                return array();
            }

            $known_groups = $registry->get_groups();

            if ( ! is_array( $known_groups ) ) {
                return array();
            }

            $known_groups = array_values(
                array_unique(
                    array_filter(
                        array_map( 'sanitize_key', $known_groups )
                    )
                )
            );

            $preferred = $this->get_preferred_groups();

            if ( empty( $preferred ) ) {
                /**
                 * Final filter for resolved group order.
                 *
                 * When no preferred order is provided, registry order wins.
                 *
                 * @param array<int,string>               $known_groups Resolved group order.
                 * @param Noesia_SWA_Settings_Panels      $registry     Settings panels registry.
                 * @param Noesia_SWA_Settings_Section_Data $this        Settings section data helper.
                 */
                $known_groups = apply_filters( 'noesia_swa_settings_group_order', $known_groups, $registry, $this );

                if ( ! is_array( $known_groups ) ) {
                    return array();
                }

                return array_values(
                    array_unique(
                        array_filter(
                            array_map( 'sanitize_key', $known_groups )
                        )
                    )
                );
            }

            $group_order = array();

            foreach ( $preferred as $group ) {
                if ( in_array( $group, $known_groups, true ) ) {
                    $group_order[] = $group;
                }
            }

            foreach ( $known_groups as $group ) {
                if ( ! in_array( $group, $group_order, true ) ) {
                    $group_order[] = $group;
                }
            }

            $group_order = apply_filters( 'noesia_swa_settings_group_order', $group_order, $registry, $this );

            if ( ! is_array( $group_order ) ) {
                return array();
            }

            return array_values(
                array_unique(
                    array_filter(
                        array_map( 'sanitize_key', $group_order )
                    )
                )
            );
        }

        /**
         * Resolve the settings panels registry.
         *
         * @return Noesia_SWA_Settings_Panels|null
         */
        public function resolve_settings_panels_registry() {
            if ( function_exists( 'noesia_swa' ) ) {
                $plugin = noesia_swa();

                if (
                    is_object( $plugin ) &&
                    isset( $plugin->settings_panels ) &&
                    $plugin->settings_panels instanceof Noesia_SWA_Settings_Panels
                ) {
                    return $plugin->settings_panels;
                }
            }

            return null;
        }
    }
}
