<?php
/**
 * Weather module (Free) — self-contained.
 *
 * Strict-isolation version:
 * - owns Weather service bootstrap
 * - owns Weather option defaults
 * - owns Weather settings sanitization
 * - provides localized option fallbacks for its local JS
 *
 * The Weather module does not need a standalone section registration here.
 * Its UI is consumed through Dashboard / Settings integrations and its own
 * local assets.
 *
 * @package Noesia_Smart_Waiter
 */

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

if ( ! class_exists( 'Noesia_Swa_Module_Weather' ) ) {

    class Noesia_Swa_Module_Weather implements Noesia_SWA_Module_Interface {

        /**
         * Get unique module ID.
         *
         * @return string
         */
        public function get_id() {
            return 'weather';
        }

        /**
         * Get module label.
         *
         * @return string
         */
        public function get_label() {
            return __( 'Weather', 'noesia-smart-waiter' );
        }

        /**
         * Get module tier.
         *
         * @return string
         */
        public function get_tier() {
            return 'free';
        }

        /**
         * Whether the module is enabled.
         *
         * @return bool
         */
        public function is_enabled() {
            return (bool) apply_filters( 'noesia_swa_module_weather_enabled', true, $this );
        }

        /**
         * Register module hooks.
         *
         * @return void
         */
        public function register_hooks() {
            $this->boot_local_weather_service();

            add_filter( 'noesia_swa_service_class', array( $this, 'filter_service_class' ), 10, 3 );
            add_filter( 'noesia_swa_service_file', array( $this, 'filter_service_file' ), 10, 4 );

            add_filter( 'noesia_swa_option_defaults', array( $this, 'filter_option_defaults' ), 10, 3 );
            add_filter( 'noesia_swa_sanitize_options', array( $this, 'sanitize_weather_fields' ), 10, 4 );
            add_filter( 'noesia_swa_localized_options', array( $this, 'filter_localized_options' ) );

            do_action( 'noesia_swa_module_weather_loaded', $this );
        }

        /**
         * Boot the module-local Weather service if it is not already loaded.
         *
         * Safe bridge step during extraction:
         * - if another loader already loaded the class, do nothing
         * - otherwise the Weather module becomes the owner of the service
         *
         * @return void
         */
        private function boot_local_weather_service() {
            if ( class_exists( 'Noesia_SWA_Weather_Service' ) ) {
                return;
            }

            $service_file = trailingslashit( __DIR__ ) . 'includes/class-noesia-swa-weather-service.php';

            if ( file_exists( $service_file ) ) {
                require_once $service_file;
            }
        }

        /**
         * Register the module-owned service class for blind consumers.
         *
         * @param string $service_class Current service class.
         * @param string $service_key   Logical service key.
         * @param mixed  $context       Caller context.
         * @return string
         */
        public function filter_service_class( $service_class, $service_key, $context ) {
            if ( 'weather' !== sanitize_key( (string) $service_key ) ) {
                return $service_class;
            }

            return 'Noesia_SWA_Weather_Service';
        }

        /**
         * Register the module-owned service bootstrap file for blind consumers.
         *
         * @param string $service_file  Current bootstrap file.
         * @param string $service_key   Logical service key.
         * @param string $service_class Resolved service class.
         * @param mixed  $context       Caller context.
         * @return string
         */
        public function filter_service_file( $service_file, $service_key, $service_class, $context ) {
            if ( 'weather' !== sanitize_key( (string) $service_key ) ) {
                return $service_file;
            }

            return trailingslashit( __DIR__ ) . 'includes/class-noesia-swa-weather-service.php';
        }

        /**
         * Provide module-owned defaults.
         *
         * @param array<string,mixed> $defaults Existing defaults.
         * @param array<string,mixed> $options Existing saved options.
         * @param mixed               $context Caller context.
         * @return array<string,mixed>
         */
        public function filter_option_defaults( $defaults, $options, $context ) {
            if ( ! is_array( $defaults ) ) {
                $defaults = array();
            }

            $defaults['weather_city']     = 'London';
            $defaults['weather_country']  = 'UK';
            $defaults['weather_units']    = 'metric';
            $defaults['weather_language'] = 'en';

            return $defaults;
        }

        /**
         * Sanitize module-owned settings fields.
         *
         * @param array<string,mixed> $new_input Sanitized output so far.
         * @param array<string,mixed> $input Raw submitted input.
         * @param array<string,mixed> $existing Previously saved options.
         * @param mixed               $admin Admin instance.
         * @return array<string,mixed>
         */
        public function sanitize_weather_fields( $new_input, $input, $existing, $admin ) {
            if ( ! is_array( $new_input ) ) {
                $new_input = array();
            }

            if ( ! is_array( $input ) ) {
                return $new_input;
            }

            if ( isset( $input['weather_city'] ) ) {
                $new_input['weather_city'] = sanitize_text_field( wp_unslash( (string) $input['weather_city'] ) );
            }

            if ( isset( $input['weather_country'] ) ) {
                $country = strtoupper( sanitize_text_field( wp_unslash( (string) $input['weather_country'] ) ) );
                $country = preg_replace( '/[^A-Z]/', '', $country );
                $new_input['weather_country'] = substr( (string) $country, 0, 2 );
            }

            if ( isset( $input['weather_units'] ) ) {
                $units = sanitize_key( wp_unslash( (string) $input['weather_units'] ) );
                $new_input['weather_units'] = in_array( $units, array( 'metric', 'imperial' ), true ) ? $units : 'metric';
            }

            if ( isset( $input['weather_language'] ) ) {
                $language          = sanitize_key( wp_unslash( (string) $input['weather_language'] ) );
                $allowed_languages = array( 'en', 'el', 'fr', 'de', 'it', 'es' );
                $new_input['weather_language'] = in_array( $language, $allowed_languages, true ) ? $language : 'en';
            }

            return $new_input;
        }

        /**
         * Ensure local JS receives the Weather fields it needs.
         *
         * @param array<string,mixed> $options Localized options payload.
         * @return array<string,mixed>
         */
        public function filter_localized_options( $options ) {
            if ( ! is_array( $options ) ) {
                $options = array();
            }

            $defaults = $this->filter_option_defaults( array(), $options, $this );

            foreach ( $defaults as $key => $default_value ) {
                if ( ! array_key_exists( $key, $options ) ) {
                    $options[ $key ] = $default_value;
                }
            }

            return $options;
        }
    }
}
