<?php
namespace GovernDocs;

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

class GovernDocs_Admin_Menu {

    const OPT_DISABLED_POST_TYPES = 'governdocs_disabled_post_types';
    const OPT_SHORTCODE_STYLE     = 'governdocs_shortcode_style';
    const OPT_ENABLED_STATUSES    = 'governdocs_enabled_statuses_by_type';

    public function hooks() : void {
        add_action( 'admin_menu', array( $this, 'register_menu' ) );
        add_action( 'admin_init', array( $this, 'register_settings' ) );
        add_filter( 'governdocs_policy_status_options', array( $this, 'filter_policy_status_options' ) );
        add_filter( 'governdocs_report_status_options', array( $this, 'filter_report_status_options' ) );
        add_filter( 'governdocs_meeting_status_options', array( $this, 'filter_meeting_status_options' ) );
    }

    public function register_menu() : void {
        add_menu_page(
            __( 'GovernDocs', 'governdocs-document-governance' ),
            __( 'GovernDocs', 'governdocs-document-governance' ),
            'manage_options',
            'governdocs-document-governance',
            array( $this, 'render_settings_page' ),
            'dashicons-media-document',
            58
        );

        add_submenu_page(
            'governdocs-document-governance',
            __( 'Settings', 'governdocs-document-governance' ),
            __( 'Settings', 'governdocs-document-governance' ),
            'manage_options',
            'governdocs-document-governance',
            array( $this, 'render_settings_page' )
        );
    }

    public function register_settings() : void {
        register_setting(
            'governdocs_settings',
            self::OPT_DISABLED_POST_TYPES,
            array(
                'type'              => 'array',
                'sanitize_callback' => array( $this, 'sanitize_disabled_post_types' ),
                'default'           => $this->default_disabled_post_types(),
            )
        );

        register_setting(
            'governdocs_settings',
            self::OPT_ENABLED_STATUSES,
            array(
                'type'              => 'array',
                'sanitize_callback' => array( $this, 'sanitize_enabled_statuses' ),
                'default'           => $this->default_enabled_statuses(),
            )
        );

        register_setting(
            'governdocs_settings',
            self::OPT_SHORTCODE_STYLE,
            array(
                'type'              => 'string',
                'sanitize_callback' => array( $this, 'sanitize_shortcode_style' ),
                'default'           => self::default_shortcode_style(),
            )
        );

        /**
         * Allow extensions such as GovernDocs PRO to register additional settings
         * on the main GovernDocs settings page.
         */
        do_action( 'governdocs_register_settings' );
    }

    private function default_disabled_post_types() : array {
        return array(
            'policies' => false,
            'meetings' => false,
            'reports'  => false,
        );
    }

    public static function default_shortcode_style() : string {
        return '1';
    }

    public static function get_shortcode_style_options() : array {
        $styles = array(
            '1' => __( 'Style 1', 'governdocs-document-governance' ),
            '2' => __( 'Style 2', 'governdocs-document-governance' ),
        );

        $styles = apply_filters( 'governdocs_shortcode_style_options', $styles );

        $out = array();

        foreach ( (array) $styles as $key => $label ) {
            $style_key = preg_replace( '/[^0-9]/', '', (string) $key );

            if ( '' === $style_key ) {
                continue;
            }

            $out[ $style_key ] = is_string( $label ) ? $label : (string) $label;
        }

        return ! empty( $out ) ? $out : array( self::default_shortcode_style() => __( 'Style 1', 'governdocs-document-governance' ) );
    }

    public static function get_shortcode_style() : string {
        $default = self::default_shortcode_style();
        $stored  = get_option( self::OPT_SHORTCODE_STYLE, $default );
        $stored  = preg_replace( '/[^0-9]/', '', (string) $stored );
        $styles  = self::get_shortcode_style_options();

        if ( '' === $stored || ! isset( $styles[ $stored ] ) ) {
            return $default;
        }

        return $stored;
    }

    public static function standard_status_options() : array {
        return array(
            'draft'    => __( 'Draft', 'governdocs-document-governance' ),
            'review'   => __( 'Under review', 'governdocs-document-governance' ),
            'approved' => __( 'Approved', 'governdocs-document-governance' ),
            'archived' => __( 'Archived', 'governdocs-document-governance' ),
        );
    }

    private function status_types() : array {
        return array(
            'policy',
            'report',
            'meeting',
        );
    }

    private function default_enabled_statuses() : array {
        $defaults     = array();
        $status_keys  = array_keys( self::standard_status_options() );

        foreach ( $this->status_types() as $type ) {
            foreach ( $status_keys as $status_key ) {
                $defaults[ $type ][ $status_key ] = true;
            }
        }

        return $defaults;
    }

    public function sanitize_disabled_post_types( $value ) : array {
        $defaults = $this->default_disabled_post_types();
        $value    = is_array( $value ) ? $value : array();

        $out = array();

        foreach ( $defaults as $key => $default ) {
            $out[ $key ] = ! empty( $value[ $key ] );
        }

        return $out;
    }

    public function sanitize_enabled_statuses( $value ) : array {
        $value        = is_array( $value ) ? $value : array();
        $defaults     = $this->default_enabled_statuses();
        $existing     = self::get_enabled_statuses();
        $status_keys  = array_keys( self::standard_status_options() );
        $out          = array();
        $fixed_types  = array();

        foreach ( $defaults as $type => $default_values ) {
            if ( ! array_key_exists( $type, $value ) ) {
                $out[ $type ] = isset( $existing[ $type ] ) && is_array( $existing[ $type ] ) ? $existing[ $type ] : $default_values;
                continue;
            }

            $type_values = is_array( $value[ $type ] ) ? $value[ $type ] : array();
            $out[ $type ] = array();

            foreach ( $status_keys as $status_key ) {
                $out[ $type ][ $status_key ] = ! empty( $type_values[ $status_key ] );
            }

            if ( empty( array_filter( $out[ $type ] ) ) ) {
                $out[ $type ] = $default_values;
                $fixed_types[] = $type;
            }
        }

        if ( ! empty( $fixed_types ) ) {
            add_settings_error(
                'governdocs_settings',
                'governdocs_enabled_statuses_empty',
                esc_html__( 'Each document type must have at least one enabled standard status. Any empty status sets were reset to the defaults.', 'governdocs-document-governance' ),
                'warning'
            );
        }

        return $out;
    }

    public function sanitize_shortcode_style( $value ) : string {
        $value  = preg_replace( '/[^0-9]/', '', (string) $value );
        $styles = self::get_shortcode_style_options();

        if ( '' === $value || ! isset( $styles[ $value ] ) ) {
            return self::default_shortcode_style();
        }

        return $value;
    }

    public static function get_disabled_post_types() : array {
        $defaults = array(
            'policies' => false,
            'meetings' => false,
            'reports'  => false,
        );

        $stored = get_option( self::OPT_DISABLED_POST_TYPES, array() );
        $stored = is_array( $stored ) ? $stored : array();

        return array(
            'policies' => array_key_exists( 'policies', $stored ) ? (bool) $stored['policies'] : $defaults['policies'],
            'meetings' => array_key_exists( 'meetings', $stored ) ? (bool) $stored['meetings'] : $defaults['meetings'],
            'reports'  => array_key_exists( 'reports', $stored ) ? (bool) $stored['reports'] : $defaults['reports'],
        );
    }

    public static function is_post_type_disabled( string $type ) : bool {
        $disabled = self::get_disabled_post_types();

        return ! empty( $disabled[ $type ] );
    }

    public static function get_enabled_statuses() : array {
        $instance = new self();
        $defaults = $instance->default_enabled_statuses();
        $stored   = get_option( self::OPT_ENABLED_STATUSES, array() );
        $stored   = is_array( $stored ) ? $stored : array();
        $out      = array();

        foreach ( $defaults as $type => $type_defaults ) {
            $type_stored = isset( $stored[ $type ] ) && is_array( $stored[ $type ] ) ? $stored[ $type ] : array();
            $out[ $type ] = array();

            foreach ( $type_defaults as $status_key => $enabled ) {
                $out[ $type ][ $status_key ] = array_key_exists( $status_key, $type_stored ) ? (bool) $type_stored[ $status_key ] : $enabled;
            }

            if ( empty( array_filter( $out[ $type ] ) ) ) {
                $out[ $type ] = $type_defaults;
            }
        }

        return $out;
    }

    public static function get_enabled_status_keys_for_type( string $type ) : array {
        $type            = sanitize_key( $type );
        $enabled_statuses = self::get_enabled_statuses();

        if ( empty( $enabled_statuses[ $type ] ) || ! is_array( $enabled_statuses[ $type ] ) ) {
            return array_keys( self::standard_status_options() );
        }

        return array_keys( array_filter( $enabled_statuses[ $type ] ) );
    }

    public function filter_policy_status_options( array $options ) : array {
        return $this->filter_status_options_for_type( $options, 'policy' );
    }

    public function filter_report_status_options( array $options ) : array {
        return $this->filter_status_options_for_type( $options, 'report' );
    }

    public function filter_meeting_status_options( array $options ) : array {
        return $this->filter_status_options_for_type( $options, 'meeting' );
    }

    private function filter_status_options_for_type( array $options, string $type ) : array {
        $enabled_keys = self::get_enabled_status_keys_for_type( $type );

        if ( empty( $enabled_keys ) ) {
            return $options;
        }

        $filtered = array();

        foreach ( $enabled_keys as $status_key ) {
            if ( isset( $options[ $status_key ] ) ) {
                $filtered[ $status_key ] = $options[ $status_key ];
            }
        }

        return ! empty( $filtered ) ? $filtered : $options;
    }

    public function render_settings_page() : void {
        if ( ! current_user_can( 'manage_options' ) ) {
            return;
        }

        $current_tab = $this->get_current_tab();
        $is_pro_active = (bool) apply_filters( 'governdocs_is_pro_active', false );

        echo '<div class="wrap governdocs-settings-page">';
        echo '<div class="governdocs-settings-hero">';
        echo '<div class="governdocs-settings-hero__brand">';
        echo '<img class="governdocs-settings-hero__logo" src="' . esc_url( GOVERNDOCS_URL . 'assets/img/governdocs-logo.png' ) . '" alt="' . esc_attr__( 'GovernDocs logo', 'governdocs-document-governance' ) . '" />';
        echo '<div>';
        echo '<h1>' . esc_html__( 'GovernDocs Settings', 'governdocs-document-governance' ) . '</h1>';

        echo '</div>';
        echo '</div>';
        echo '<div class="governdocs-settings-hero__status">';
        echo '<span class="governdocs-settings-badge ' . ( $is_pro_active ? 'is-pro' : 'is-free' ) . '">';
        echo esc_html( $is_pro_active ? __( 'PRO Active', 'governdocs-document-governance' ) : __( 'Free Version', 'governdocs-document-governance' ) );
        echo '</span>';
        echo '</div>';
        echo '</div>';

        echo '<div class="governdocs-settings-notices">';
        settings_errors( 'governdocs_settings' );
        echo '</div>';

        $this->render_settings_tabs( $current_tab );

        echo '<div class="governdocs-settings-layout">';
        echo '<div class="governdocs-settings-main">';
        echo '<form method="post" action="options.php">';
        settings_fields( 'governdocs_settings' );

        $this->render_tab_content( $current_tab );

        echo '<div class="governdocs-settings-actions">';
        submit_button( __( 'Save Settings', 'governdocs-document-governance' ) );
        echo '</div>';
        echo '</form>';
        echo '</div>';

        echo '<aside class="governdocs-settings-sidebar">';
        $this->render_sidebar_card(
            __( 'Help & Support', 'governdocs-document-governance' ),
            __( 'Need guidance with setup, publishing, or shortcode output?', 'governdocs-document-governance' ),
            array(
                array(
                    'label' => __( 'View Docs', 'governdocs-document-governance' ),
                    'url'   => 'https://governdocs.com/docs',
                ),
            )
        );

        $this->render_sidebar_card(
            __( 'Upgrade to PRO', 'governdocs-document-governance' ),
            __( 'GovernDocs PRO adds stronger governance tooling for teams that need more traceability, structure, and flexibility.', 'governdocs-document-governance' ),
            array(
                array(
                    'label' => __( 'View PRO Features', 'governdocs-document-governance' ),
                    'url'   => 'https://governdocs.com/pricing',
                    'class' => 'button button-primary',
                ),
            )
        );

        echo '</aside>';
        echo '</div>';
        echo '</div>';
    }

    private function render_sidebar_card( string $title, string $description, array $actions = array() ) : void {
        echo '<div class="governdocs-settings-card governdocs-settings-card--sidebar">';
        echo '<h2>' . esc_html( $title ) . '</h2>';
        echo '<p>' . esc_html( $description ) . '</p>';

        if ( ! empty( $actions ) ) {
            echo '<div class="governdocs-settings-card__actions">';

            foreach ( $actions as $action ) {
                $label = isset( $action['label'] ) ? (string) $action['label'] : '';
                $url   = isset( $action['url'] ) ? (string) $action['url'] : '';
                $class = isset( $action['class'] ) ? (string) $action['class'] : 'button';

                if ( '' === $label || '' === $url ) {
                    continue;
                }

                echo '<a class="' . esc_attr( $class ) . '" href="' . esc_url( $url ) . '" target="_blank" rel="noopener noreferrer">' . esc_html( $label ) . '</a>';
            }

            echo '</div>';
        }

        echo '</div>';
    }

    private function get_settings_tabs() : array {
        return array(
            'global'   => __( 'Global Settings', 'governdocs-document-governance' ),
            'policy'   => __( 'Policy Settings', 'governdocs-document-governance' ),
            'reports'  => __( 'Reports Settings', 'governdocs-document-governance' ),
            'meetings' => __( 'Meetings Settings', 'governdocs-document-governance' ),
        );
    }

    private function get_current_tab() : string {
        $tabs = $this->get_settings_tabs();
        $tab  = filter_input( INPUT_GET, 'tab', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
        $tab  = is_string( $tab ) ? sanitize_key( $tab ) : 'global';

        return array_key_exists( $tab, $tabs ) ? $tab : 'global';
    }

    private function render_settings_tabs( string $current_tab ) : void {
        $tabs     = $this->get_settings_tabs();
        $base_url = admin_url( 'admin.php?page=governdocs-document-governance' );

        echo '<nav class="nav-tab-wrapper governdocs-settings-tabs" aria-label="' . esc_attr__( 'GovernDocs settings sections', 'governdocs-document-governance' ) . '">';

        foreach ( $tabs as $tab_key => $label ) {
            $classes = 'nav-tab';

            if ( $current_tab === $tab_key ) {
                $classes .= ' nav-tab-active';
            }

            echo '<a class="' . esc_attr( $classes ) . '" href="' . esc_url( add_query_arg( 'tab', $tab_key, $base_url ) ) . '">';
            echo esc_html( $label );
            echo '</a>';
        }

        echo '</nav>';
    }

    private function render_tab_content( string $current_tab ) : void {
        switch ( $current_tab ) {
            case 'policy':
                $this->render_post_type_tab(
                    'policy',
                    'governdocs_render_settings_tab_policy'
                );
                return;

            case 'reports':
                $this->render_post_type_tab(
                    'report',
                    'governdocs_render_settings_tab_reports'
                );
                return;

            case 'meetings':
                $this->render_post_type_tab(
                    'meeting',
                    'governdocs_render_settings_tab_meetings'
                );
                return;

            case 'global':
            default:
                $this->render_global_tab();
                return;
        }
    }

    private function render_global_tab() : void {
        $disabled = self::get_disabled_post_types();
        $style    = self::get_shortcode_style();
        $styles   = self::get_shortcode_style_options();

        echo '<div class="governdocs-settings-card">';
        echo '<div class="governdocs-settings-card__header">';
        echo '<h2>' . esc_html__( 'Content Types', 'governdocs-document-governance' ) . '</h2>';
        echo '<p>' . esc_html__( 'Disable any GovernDocs content types you do not want to use.', 'governdocs-document-governance' ) . '</p>';
        echo '</div>';
        echo '<table class="form-table" role="presentation"><tbody>';

        $this->render_switch_row(
            'policies',
            __( 'Disable Policies', 'governdocs-document-governance' ),
            $disabled['policies'],
            __( 'Turn off the Policies content type throughout GovernDocs.', 'governdocs-document-governance' )
        );

        $this->render_switch_row(
            'meetings',
            __( 'Disable Meetings', 'governdocs-document-governance' ),
            $disabled['meetings'],
            __( 'Turn off the Meetings content type throughout GovernDocs.', 'governdocs-document-governance' )
        );

        $this->render_switch_row(
            'reports',
            __( 'Disable Reports', 'governdocs-document-governance' ),
            $disabled['reports'],
            __( 'Turn off the Reports content type throughout GovernDocs.', 'governdocs-document-governance' )
        );

        echo '</tbody></table>';
        echo '</div>';

        echo '<div class="governdocs-settings-card">';
        echo '<div class="governdocs-settings-card__header">';
        echo '<h2>' . esc_html__( 'Frontend Style', 'governdocs-document-governance' ) . '</h2>';
        echo '<p>' . esc_html__( 'Default style used by GovernDocs shortcode output. Individual shortcodes can still override this with the style attribute.', 'governdocs-document-governance' ) . '</p>';
        echo '</div>';
        echo '<table class="form-table" role="presentation"><tbody>';
        echo '<tr>';
        echo '<th scope="row"><label for="governdocs_shortcode_style">' . esc_html__( 'Default Style', 'governdocs-document-governance' ) . '</label></th>';
        echo '<td>';
        echo '<select id="governdocs_shortcode_style" name="' . esc_attr( self::OPT_SHORTCODE_STYLE ) . '">';

        foreach ( $styles as $style_key => $style_label ) {
            echo '<option value="' . esc_attr( $style_key ) . '" ' . selected( $style, $style_key, false ) . '>' . esc_html( $style_label ) . '</option>';
        }

        echo '</select>';
        echo '<p class="description">';
        echo esc_html__( 'Use style="2" in shortcode to override global style.', 'governdocs-document-governance' ) . ' ';
        echo '<a href="' . esc_url( 'https://governdocs.com/pricing' ) . '" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Upgrade for more styles', 'governdocs-document-governance' ) . '</a>';
        echo '</p>';
        echo '</td>';
        echo '</tr>';
        echo '</tbody></table>';
        echo '</div>';

        do_action( 'governdocs_render_settings_tab_global' );
    }

    private function render_post_type_tab( string $type, string $hook_name ) : void {
        $this->render_status_settings_card( $type );

        do_action( $hook_name );
    }

    private function render_status_settings_card( string $type ) : void {
        $statuses      = self::standard_status_options();
        $enabled       = self::get_enabled_statuses();
        $enabled_type  = isset( $enabled[ $type ] ) && is_array( $enabled[ $type ] ) ? $enabled[ $type ] : array();
        $is_pro_active = (bool) apply_filters( 'governdocs_is_pro_active', false );

        echo '<div class="governdocs-settings-card">';
        echo '<div class="governdocs-settings-card__header">';
        echo '<h2>' . esc_html__( 'Status Settings', 'governdocs-document-governance' ) . '</h2>';
        echo '<p>' . esc_html__( 'Choose which of the standard statuses should be available for this document type.', 'governdocs-document-governance' ) . '</p>';
        echo '</div>';
        echo '<table class="form-table" role="presentation"><tbody>';

        foreach ( $statuses as $status_key => $status_label ) {
            $is_enabled = ! empty( $enabled_type[ $status_key ] );

            $this->render_status_switch_row(
                $type,
                $status_key,
                sprintf(
                    /* translators: %s: status label */
                    __( 'Enable %s', 'governdocs-document-governance' ),
                    $status_label
                ),
                $is_enabled
            );
        }

        echo '</tbody></table>';

        if ( ! $is_pro_active ) {
            echo '<div class="governdocs-settings-upgrade-note">';
            echo '<p><strong>' . esc_html__( 'Upgrade to add custom statuses', 'governdocs-document-governance' ) . '</strong></p>';
            echo '<p>' . esc_html__( 'GovernDocs PRO lets you add your own custom statuses for each document type, alongside the standard ones.', 'governdocs-document-governance' ) . '</p>';
            echo '<p><a class="button" target="_blank" rel="noopener noreferrer" href="https://governdocs.com/pricing">' . esc_html__( 'View PRO Features', 'governdocs-document-governance' ) . '</a></p>';
            echo '</div>';
        } else {
            do_action( 'governdocs_render_status_settings_extension_' . $type );
        }

        echo '</div>';
    }

    private function render_status_switch_row( string $type, string $status_key, string $label, bool $checked ) : void {
        echo '<tr>';
        echo '<th scope="row">' . esc_html( $label ) . '</th>';
        echo '<td>';

        $id = 'governdocs_status_' . esc_attr( $type ) . '_' . esc_attr( $status_key );

        printf(
            '<label class="governdocs-switch">
                <input type="checkbox" id="%1$s" name="%2$s[%3$s][%4$s]" value="1" %5$s>
                <span class="governdocs-slider"></span>
            </label>',
            esc_attr( $id ),
            esc_attr( self::OPT_ENABLED_STATUSES ),
            esc_attr( $type ),
            esc_attr( $status_key ),
            checked( $checked, true, false )
        );

        echo '</td>';
        echo '</tr>';
    }

    private function render_switch_row( string $key, string $label, bool $checked, string $description ) : void {
        echo '<tr>';
        echo '<th scope="row">' . esc_html( $label ) . '</th>';
        echo '<td>';

        $id = 'governdocs_switch_' . esc_attr( $key );

        printf(
            '<label class="governdocs-switch">
                <input type="checkbox" id="%1$s" name="%2$s[%3$s]" value="1" %4$s>
                <span class="governdocs-slider"></span>
            </label>
            <p class="description">%5$s</p>',
            esc_attr( $id ),
            esc_attr( self::OPT_DISABLED_POST_TYPES ),
            esc_attr( $key ),
            checked( $checked, true, false ),
            esc_html( $description )
        );

        echo '</td>';
        echo '</tr>';
    }
}