<?php
/**
 * Free Appointments module.
 *
 * Strict-isolation entrypoint for the Appointments admin section.
 * Owns:
 * - section registration
 * - local Appointments AJAX bootstrap
 * - local Appointments CPT bootstrap
 * - local eager assets on the plugin admin page because the module projects
 *   live UI into the Dashboard / header
 * - Appointments-specific shared i18n used by its module-local JS
 * - module-owned topbar action metadata for the shared shell
 *
 * @package Noesia_Smart_Waiter
 */

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

if ( ! class_exists( 'Noesia_Swa_Module_Appointments' ) ) {
    /**
     * Free Appointments module.
     */
    class Noesia_Swa_Module_Appointments implements Noesia_SWA_Module_Interface {

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

        /**
         * Human-readable module label.
         *
         * @return string
         */
        public function get_label() {
            return __( 'Appointments', '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 Appointments module is enabled.
             *
             * @param bool                           $enabled Enabled state.
             * @param Noesia_Swa_Module_Appointments $module  Module instance.
             */
            $enabled = apply_filters( 'noesia_swa_module_appointments_enabled', $enabled, $this );

            return (bool) $enabled;
        }

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

            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_topbar_actions', array( $this, 'filter_topbar_actions' ), 20, 4 );
            add_filter( 'noesia_swa_factory_reset_post_types', array( $this, 'filter_factory_reset_post_types' ), 10, 2 );

            /**
             * Fires when the Appointments module is booted.
             *
             * @param Noesia_Swa_Module_Appointments $this Module instance.
             */
            do_action( 'noesia_swa_module_appointments_loaded', $this );
        }

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

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

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

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

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

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

        /**
         * Register the Appointments 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'          => 'appointments',
                    'label'       => $this->get_label(),
                    'nav_label'   => $this->get_label(),
                    'nav_sub'     => __( 'Schedule & Visits', 'noesia-smart-waiter' ),
                    'icon'        => 'dashicons-calendar-alt',
                    'priority'    => 90,
                    'tier'        => 'free',
                    'owner'       => 'appointments',
                    'is_visible'  => true,
                    'nav_visible' => true,
                    'callback'    => array( $this, 'render_admin' ),
                )
            );
        }

        /**
         * Provide Appointments-owned i18n used by its 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['appt_required_fields']       = __( 'Date, Start Time, and Guest Name are required.', 'noesia-smart-waiter' );
            $i18n['appt_backend_not_ready']     = __( 'Appointments backend is not ready yet.', 'noesia-smart-waiter' );
            $i18n['appt_save_error']            = __( 'Could not save appointment.', 'noesia-smart-waiter' );
            $i18n['appt_backend_not_connected'] = __( 'Appointments backend is not connected yet.', 'noesia-smart-waiter' );

            return $i18n;
        }

        /**
         * Register the Appointments topbar action inside the shared shell.
         *
         * Transitional ownership move:
         * - today the shell still has default topbar actions
         * - this module now asserts ownership of the appointments action metadata
         * - later, kernel defaults can be emptied safely
         *
         * @param array<int,array<string,mixed>>    $actions Existing topbar actions.
         * @param array<string,array<string,mixed>> $sections Registered admin sections.
         * @param array<string,mixed>               $options Saved options.
         * @param mixed                             $shell_data Shell data helper.
         * @return array<int,array<string,mixed>>
         */
        public function filter_topbar_actions( $actions, $sections, $options, $shell_data ) {
            if ( ! is_array( $actions ) ) {
                $actions = array();
            }

            $replacement = array(
                'id'       => 'appointments',
                'type'     => 'nav',
                'target'   => 'appointments',
                'icon'     => 'dashicons-calendar-alt',
                'label'    => __( 'Appointments', 'noesia-smart-waiter' ),
                'position' => 'left',
                'priority' => 40,
                'owner'    => 'appointments',
            );

            $found = false;

            foreach ( $actions as $index => $action ) {
                if ( ! is_array( $action ) ) {
                    continue;
                }

                $action_id     = isset( $action['id'] ) ? sanitize_key( (string) $action['id'] ) : '';
                $action_target = isset( $action['target'] ) ? sanitize_key( (string) $action['target'] ) : '';

                if ( 'appointments' === $action_id || 'appointments' === $action_target ) {
                    $actions[ $index ] = array_merge( $action, $replacement );
                    $found             = true;
                    break;
                }
            }

            if ( ! $found ) {
                $actions[] = $replacement;
            }

            return $actions;
        }


        /**
         * Register Appointments-owned entities for the factory reset pipeline.
         *
         * @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_appointment';

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

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

            /**
             * Fires before the Appointments admin module view renders.
             *
             * @param Noesia_Swa_Module_Appointments $this Module instance.
             */
            do_action( 'noesia_swa_before_render_appointments_admin', $this );

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

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

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

                /**
                 * Fires after the Appointments legacy fallback view renders.
                 *
                 * @param Noesia_Swa_Module_Appointments $this Module instance.
                 */
                do_action( 'noesia_swa_after_render_appointments_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__( 'Appointments', '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 Appointments missing-view fallback renders.
             *
             * @param Noesia_Swa_Module_Appointments $this Module instance.
             */
            do_action( 'noesia_swa_after_render_appointments_admin', $this );
        }
    }
}
