<?php
/**
 * News module (Free) — self-contained.
 *
 * Strict-isolation version:
 * - owns its local News service bootstrap
 * - owns its AJAX bootstrap
 * - owns its defaults
 * - owns sanitization of News settings
 * - provides localized options needed by its local JS
 *
 * Assets remain lazy-loaded by the shell manifest. This file must not enqueue
 * module assets directly.
 *
 * @package Noesia_Smart_Waiter
 */

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

if ( ! class_exists( 'Noesia_SWA_Module_News' ) ) {

    class Noesia_SWA_Module_News implements Noesia_SWA_Module_Interface {

        public function get_id() {
            return 'news';
        }

        public function get_label() {
            return __( 'News', 'noesia-smart-waiter' );
        }

        public function get_tier() {
            return 'free';
        }

        public function is_enabled() {
            return (bool) apply_filters( 'noesia_swa_module_news_enabled', true, $this );
        }

        public function register_hooks() {
            $this->boot_local_news_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_action( 'noesia_swa_register_admin_sections', array( $this, 'register_admin_section' ) );

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

            $ajax_file = trailingslashit( __DIR__ ) . 'includes/class-noesia-swa-module-news-ajax.php';
            if ( file_exists( $ajax_file ) ) {
                require_once $ajax_file;

                if ( class_exists( 'Noesia_SWA_Module_News_Ajax' ) ) {
                    new Noesia_SWA_Module_News_Ajax();
                }
            }

            do_action( 'noesia_swa_module_news_loaded', $this );
        }

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

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

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

        /**
         * Register standalone News section/tab.
         *
         * @param mixed $registry Admin sections registry.
         * @return void
         */
        public function register_admin_section( $registry ) {
            if ( ! is_object( $registry ) || ! method_exists( $registry, 'register_section' ) ) {
                return;
            }

            $registry->register_section(
                array(
                    'id'          => 'news',
                    'label'       => $this->get_label(),
                    'nav_label'   => $this->get_label(),
                    'nav_sub'     => __( 'Headlines & Briefing', 'noesia-smart-waiter' ),
                    'icon'        => 'dashicons-media-document',
                    'priority'    => 15,
                    'tier'        => 'free',
                    'owner'       => 'news',
                    'is_visible'  => true,
                    'nav_visible' => true,
                    'callback'    => array( $this, 'render_admin' ),
                )
            );
        }

        /**
         * 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 ( 'news' !== sanitize_key( (string) $service_key ) ) {
                return $service_class;
            }

            return 'Noesia_SWA_News_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 ( 'news' !== sanitize_key( (string) $service_key ) ) {
                return $service_file;
            }

            return trailingslashit( __DIR__ ) . 'includes/class-noesia-swa-news-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['news_language'] = 'en';
            $defaults['news_country']  = '';

            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_news_fields( $new_input, $input, $existing, $admin ) {
            if ( ! is_array( $new_input ) ) {
                $new_input = array();
            }

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

            if ( isset( $input['news_language'] ) ) {
                $allowed_languages = array( 'en', 'el', 'de', 'fr', 'it', 'es' );
                $language          = sanitize_key( wp_unslash( (string) $input['news_language'] ) );

                if ( ! in_array( $language, $allowed_languages, true ) ) {
                    $language = 'en';
                }

                $new_input['news_language'] = $language;
            }

            if ( isset( $input['news_country'] ) ) {
                $country = strtoupper( sanitize_text_field( wp_unslash( (string) $input['news_country'] ) ) );
                $country = preg_replace( '/[^A-Z]/', '', $country );

                $new_input['news_country'] = substr( (string) $country, 0, 2 );
            }

            return $new_input;
        }

        /**
         * Ensure the shell bridge receives the fields this module 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;
        }

        /**
         * Render News admin view.
         *
         * @return void
         */
        public function render_admin() {
            $view = trailingslashit( __DIR__ ) . 'views/admin.php';
            if ( file_exists( $view ) ) {
                include $view;
                return;
            }

            echo '<div class="noesia-swa-card noesia-swa-card--span2">';
            echo '<div class="noesia-swa-card-header"><div>';
            echo '<h3>' . esc_html__( 'News', 'noesia-smart-waiter' ) . '</h3>';
            echo '<p class="noesia-swa-muted">' . esc_html__( 'Missing view file.', 'noesia-smart-waiter' ) . '</p>';
            echo '</div></div></div>';
        }
    }
}
