<?php
/**
 * Free Design / Live Requests module.
 *
 * Strict-isolation entrypoint for the Design admin section.
 * Owns:
 * - section registration
 * - module-local admin view
 * - request/live-request shared i18n used by the shell bridge / local JS
 * - live requests badge context for the shared shell
 * - transitional ownership of Public/App settings fields until the public layer
 *   is fully isolated in a later phase
 * - bootstrap of the transitional module-local Public/App runtime
 * - bootstrap of the module-local Design / Live Requests AJAX handlers
 * - bootstrap of the module-local Design / Live Requests CPT
 * - bootstrap of the module-local Design / Live Requests cron cleanup
 *
 * @package Noesia_Smart_Waiter
 */

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

if ( ! class_exists( 'Noesia_Swa_Module_Design' ) ) {
    /**
     * Free Design / Live Requests module.
     */
    class Noesia_Swa_Module_Design implements Noesia_SWA_Module_Interface {

        /**
         * Unique module identifier.
         *
         * @return string
         */
        public function get_id() {
            return 'design';
        }

        /**
         * Human-readable module label.
         *
         * @return string
         */
        public function get_label() {
            return __( 'Design / Live Requests', 'noesia-smart-waiter' );
        }

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

        /**
         * Whether the module is enabled.
         *
         * @return bool
         */
        public function is_enabled() {
            $enabled = true;

            /**
             * Filter whether the free Design module is enabled.
             *
             * @param bool                      $enabled Enabled state.
             * @param Noesia_Swa_Module_Design $module  Module instance.
             */
            $enabled = apply_filters( 'noesia_swa_module_design_enabled', $enabled, $this );

            return (bool) $enabled;
        }

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

            add_action( 'noesia_swa_register_admin_sections', array( $this, 'register_admin_section' ) );

            add_filter( 'noesia_swa_admin_i18n', array( $this, 'filter_admin_i18n' ), 10, 2 );
            add_filter( 'noesia_swa_shell_active_badge_context', array( $this, 'filter_active_badge_context' ), 10, 3 );
            add_filter( 'noesia_swa_option_defaults', array( $this, 'filter_option_defaults' ), 10, 3 );
            add_filter( 'noesia_swa_sanitize_options', array( $this, 'sanitize_public_app_fields' ), 10, 4 );
            add_filter( 'noesia_swa_localized_options', array( $this, 'filter_localized_options' ) );
            add_filter( 'noesia_swa_factory_reset_post_types', array( $this, 'filter_factory_reset_post_types' ), 10, 2 );

            /**
             * Fires when the Design module is booted.
             *
             * @param Noesia_Swa_Module_Design $this Module instance.
             */
            do_action( 'noesia_swa_module_design_loaded', $this );
        }

        /**
         * Boot the transitional module-local Public/App runtime if it is not
         * already loaded.
         *
         * @return void
         */
        private function boot_local_public_runtime() {
            if ( class_exists( 'Noesia_SWA_Public' ) ) {
                return;
            }

            $runtime_file = trailingslashit( __DIR__ ) . 'includes/class-noesia-swa-public.php';

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

        /**
         * Boot the module-local Design / Live Requests AJAX handlers.
         *
         * @return void
         */
        private function boot_local_ajax_handlers() {
            $ajax_file = trailingslashit( __DIR__ ) . 'includes/class-noesia-swa-module-design-ajax.php';

            if ( file_exists( $ajax_file ) ) {
                require_once $ajax_file;

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

        /**
         * Boot the module-local Live Requests CPT owner.
         *
         * @return void
         */
        private function boot_local_cpt() {
            $cpt_file = trailingslashit( __DIR__ ) . 'includes/class-noesia-swa-module-design-cpt.php';

            if ( file_exists( $cpt_file ) ) {
                require_once $cpt_file;

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

        /**
         * Boot the module-local Design cron cleanup owner.
         *
         * @return void
         */
        private function boot_local_cron() {
            $cron_file = trailingslashit( __DIR__ ) . 'includes/class-noesia-swa-module-design-cron.php';

            if ( file_exists( $cron_file ) ) {
                require_once $cron_file;

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

        /**
         * Register the Design / Live Requests admin section.
         *
         * @param mixed $registry Admin sections registry.
         * @return void
         */
        public function register_admin_section( $registry ) {
            if ( ! $registry instanceof Noesia_SWA_Admin_Sections ) {
                return;
            }

            $registry->register_section(
                array(
                    'id'          => 'design',
                    'label'       => $this->get_label(),
                    'nav_label'   => __( 'Design', 'noesia-smart-waiter' ),
                    'nav_sub'     => __( 'Live Requests & Branding', 'noesia-smart-waiter' ),
                    'icon'        => 'dashicons-admin-customizer',
                    'priority'    => 90,
                    'tier'        => 'free',
                    'owner'       => 'design',
                    'is_visible'  => true,
                    'nav_visible' => true,
                    'callback'    => array( $this, 'render_admin' ),
                )
            );
        }

        /**
         * Provide Design / Live Requests-owned i18n used by shell/local JS.
         *
         * @param array<string,string> $i18n Existing i18n payload.
         * @param mixed                $admin Admin instance.
         * @return array<string,string>
         */
        public function filter_admin_i18n( $i18n, $admin ) {
            if ( ! is_array( $i18n ) ) {
                $i18n = array();
            }

            $i18n['requests_empty']         = __( 'No active requests right now.', 'noesia-smart-waiter' );
            $i18n['request_label']          = __( 'Request', 'noesia-smart-waiter' );
            $i18n['briefing_open_design']   = __( 'Open Design / Live Requests', 'noesia-smart-waiter' );
            $i18n['badge_requests_label']   = __( 'Active Requests', 'noesia-smart-waiter' );
            $i18n['badge_request_singular'] = __( 'Active Request', 'noesia-smart-waiter' );

            return $i18n;
        }

        /**
         * Provide live Requests badge context to the shared shell.
         *
         * @param array<string,mixed> $context Default shell context.
         * @param array<string,mixed> $options Saved options.
         * @param mixed               $helper Shell data helper.
         * @return array<string,mixed>
         */
        public function filter_active_badge_context( $context, $options, $helper ) {
            if ( ! is_array( $context ) ) {
                $context = array();
            }

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

            $source = '';

            if ( ! empty( $options['dashboard_stats_source'] ) ) {
                $source = sanitize_key( (string) $options['dashboard_stats_source'] );
            } elseif ( ! empty( $options['global_active_badge_type'] ) ) {
                $source = sanitize_key( (string) $options['global_active_badge_type'] );
            }

            if ( 'requests' !== $source ) {
                return $context;
            }

            $count = $this->get_active_requests_count();

            return array_merge(
                $context,
                array(
                    'type'           => 'requests',
                    'visible'        => $count > 0,
                    'count'          => $count,
                    'label'          => ( 1 === $count ) ? __( 'Active Request', 'noesia-smart-waiter' ) : __( 'Active Requests', 'noesia-smart-waiter' ),
                    'text'           => ( 1 === $count ) ? __( 'Active Request', 'noesia-smart-waiter' ) : __( 'Active Requests', 'noesia-smart-waiter' ),
                    'target'         => 'design',
                    'requests_count' => $count,
                    'requests_text'  => ( 1 === $count ) ? __( 'Active Request', 'noesia-smart-waiter' ) : __( 'Active Requests', 'noesia-smart-waiter' ),
                )
            );
        }

        /**
         * Count currently active requests.
         *
         * @return int
         */
        private function get_active_requests_count() {
            $query = new WP_Query(
                array(
                    'post_type'      => 'noesia_request',
                    'post_status'    => array( 'publish', 'private' ),
                    'posts_per_page' => -1,
                    'fields'         => 'ids',
                    // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Active/completed request state is stored in post meta for this module and the current CPT volume is expected to stay small.
                    'meta_query'     => array(
                        array(
                            'key'   => 'noesia_status',
                            'value' => 'active',
                        ),
                    ),
                )
            );

            return absint( $query->found_posts );
        }

        /**
         * Provide transitional defaults for Public/App fields.
         *
         * @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 = array_merge(
                $defaults,
                array(
                    'shop_name'    => '',
                    'btn_menu'     => __( 'View Our Menu', 'noesia-smart-waiter' ),
                    'icon_menu'    => '📜',
                    'btn_order'    => __( 'New Order', 'noesia-smart-waiter' ),
                    'icon_order'   => '🍽️',
                    'btn_waiter'   => __( 'Call Waiter', 'noesia-smart-waiter' ),
                    'icon_waiter'  => '🙋',
                    'btn_bill'     => __( 'Bill Please', 'noesia-smart-waiter' ),
                    'icon_bill'    => '💳',
                    'cst1_label'   => __( 'Urgent', 'noesia-smart-waiter' ),
                    'cst1_icon'    => '💧',
                    'cst2_label'   => __( 'Pool pls', 'noesia-smart-waiter' ),
                    'cst2_icon'    => '✨',
                    'rate_label'   => __( 'Rate Us on Google', 'noesia-smart-waiter' ),
                    'color_bg'     => '#0f172a',
                    'color_title'  => '#ffffff',
                    'color_text'   => '#cbd5e1',
                    'sound_enable' => '1',
                    'menu_active'  => '1',
                    'logo_url'     => '',
                    'review_url'   => '',
                    'menu_url'     => '',
                )
            );

            return $defaults;
        }

        /**
         * Sanitize transitional Public/App 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_public_app_fields( $new_input, $input, $existing, $admin ) {
            if ( ! is_array( $new_input ) ) {
                $new_input = array();
            }

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

            $text_fields = array(
                'shop_name',
                'btn_menu',
                'btn_order',
                'btn_waiter',
                'btn_bill',
                'cst1_label',
                'cst2_label',
                'rate_label',
            );

            foreach ( $text_fields as $field ) {
                if ( isset( $input[ $field ] ) ) {
                    $new_input[ $field ] = sanitize_text_field( wp_unslash( (string) $input[ $field ] ) );
                }
            }

            $icon_fields = array(
                'icon_menu',
                'icon_order',
                'icon_waiter',
                'icon_bill',
                'cst1_icon',
                'cst2_icon',
            );

            foreach ( $icon_fields as $field ) {
                if ( isset( $input[ $field ] ) ) {
                    $new_input[ $field ] = sanitize_text_field( wp_unslash( (string) $input[ $field ] ) );
                }
            }

            $color_fields = array(
                'color_bg',
                'color_title',
                'color_text',
            );

            foreach ( $color_fields as $field ) {
                if ( isset( $input[ $field ] ) ) {
                    $new_input[ $field ] = sanitize_hex_color( wp_unslash( (string) $input[ $field ] ) ) ?: '';
                }
            }

            $url_fields = array(
                'logo_url',
                'review_url',
                'menu_url',
            );

            foreach ( $url_fields as $field ) {
                if ( isset( $input[ $field ] ) ) {
                    $new_input[ $field ] = esc_url_raw( wp_unslash( (string) $input[ $field ] ) );
                }
            }

            $new_input['sound_enable'] = isset( $input['sound_enable'] ) ? '1' : '0';
            $new_input['menu_active']  = isset( $input['menu_active'] ) ? '1' : '0';

            return $new_input;
        }

        /**
         * Ensure localized options contain transitional Public/App fields.
         *
         * @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;
        }


        /**
         * Register Design-owned entities for the factory reset pipeline.
         *
         * The kernel no longer needs to know this module's CPT slug.
         * Future Pro/public modules can follow the same contract.
         *
         * @param array<int,string> $post_types Existing reset post types.
         * @param mixed             $ajax_handler AJAX handler instance.
         * @return array<int,string>
         */
        public function filter_factory_reset_post_types( $post_types, $ajax_handler ) {
            if ( ! is_array( $post_types ) ) {
                $post_types = array();
            }

            $post_types[] = 'noesia_request';

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

        /**
         * Render the module-local Design admin view.
         *
         * @return void
         */
        public function render_admin() {
            $module_view = trailingslashit( __DIR__ ) . 'views/admin.php';
            $legacy_view = NOESIA_SWA_PLUGIN_DIR . 'admin/partials/sections/design.php';

            /**
             * Fires before the Design admin module view renders.
             *
             * @param Noesia_Swa_Module_Design $this Module instance.
             */
            do_action( 'noesia_swa_before_render_design_admin', $this );

            if ( file_exists( $module_view ) ) {
                include $module_view;

                /**
                 * Fires after the Design admin module view renders.
                 *
                 * @param Noesia_Swa_Module_Design $this Module instance.
                 */
                do_action( 'noesia_swa_after_render_design_admin', $this );
                return;
            }

            if ( file_exists( $legacy_view ) ) {
                include $legacy_view;

                /**
                 * Fires after the Design legacy fallback view renders.
                 *
                 * @param Noesia_Swa_Module_Design $this Module instance.
                 */
                do_action( 'noesia_swa_after_render_design_admin', $this );
                return;
            }

            echo '<div class="noesia-swa-card noesia-swa-card--span2">';
            echo '<div class="noesia-swa-card-header"><div>';
            echo '<h3>' . esc_html__( 'Design / Live Requests', 'noesia-smart-waiter' ) . '</h3>';
            echo '<p class="noesia-swa-muted">' . esc_html__( 'Module view missing.', 'noesia-smart-waiter' ) . '</p>';
            echo '</div></div>';
            echo '</div>';

            /**
             * Fires after the Design missing-view fallback renders.
             *
             * @param Noesia_Swa_Module_Design $this Module instance.
             */
            do_action( 'noesia_swa_after_render_design_admin', $this );
        }
    }
}
