<?php

namespace AIPT\Api\BulkGenerator\FAQ;

use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;
use WP_Error;

/**
 * FAQ Display Settings REST API Controller.
 *
 * Exposes GET, POST, and DELETE endpoints under aipt/v1/faq-display-settings
 * for reading, updating, and resetting FAQ accordion display preferences.
 *
 * @package AIPT\Api\BulkGenerator\FAQ
 * @since   2.5.0
 */
class FAQDisplaySettingsController {

    /**
     * FAQ display settings instance.
     *
     * @var FAQDisplaySettings
     */
    private $faq_display_settings;

    /**
     * Constructor.
     *
     * @param FAQDisplaySettings|null $faq_display_settings Optional instance for dependency injection.
     */
    public function __construct( ?FAQDisplaySettings $faq_display_settings = null ) {
        $this->faq_display_settings = $faq_display_settings ?? new FAQDisplaySettings();
    }

    /**
     * Register REST API routes.
     *
     * Registers GET (read settings + defaults), POST (save settings), and
     * DELETE (reset to defaults) routes at aipt/v1/faq-display-settings.
     * Hook registration is handled externally via rest_api_init in Init.php.
     *
     * @return void
     */
    public function register_routes(): void {
        register_rest_route( 'aipt/v1', '/faq-display-settings', [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [ $this, 'get_settings' ],
                'permission_callback' => [ $this, 'check_permissions' ],
            ],
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [ $this, 'update_settings' ],
                'permission_callback' => [ $this, 'check_permissions_write' ],
                'args'                => [
                    'settings' => [
                        'required'          => true,
                        'type'              => 'object',
                        'validate_callback' => function ( $param ) {
                            if ( ! is_array( $param ) ) {
                                return new WP_Error(
                                    'invalid_settings',
                                    __( 'Settings must be an object.', 'ai-product-tools' ),
                                    [ 'status' => 400 ]
                                );
                            }
                            return true;
                        },
                        'sanitize_callback' => function ( $param ) {
                            return is_array( $param ) ? $param : [];
                        },
                    ],
                ],
            ],
            [
                'methods'             => WP_REST_Server::DELETABLE,
                'callback'            => [ $this, 'reset_settings' ],
                'permission_callback' => [ $this, 'check_permissions_write' ],
            ],
        ] );
    }

    /**
     * Check permissions for read operations (GET).
     *
     * Requires the manage_woocommerce capability so Shop Managers can
     * access the Display tab inside the FAQ Generator page.
     *
     * @param WP_REST_Request $request Incoming REST request.
     * @return bool|WP_Error True on success, WP_Error on insufficient permissions.
     */
    public function check_permissions( $request ) {
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            return new WP_Error(
                'rest_forbidden',
                __( 'You do not have permission to access this resource.', 'ai-product-tools' ),
                [ 'status' => 403 ]
            );
        }

        return true;
    }

    /**
     * Check permissions for write operations (POST / DELETE).
     *
     * Requires manage_woocommerce capability and a valid REST nonce.
     *
     * @param WP_REST_Request $request Incoming REST request.
     * @return bool|WP_Error True on success, WP_Error on insufficient permissions or bad nonce.
     */
    public function check_permissions_write( $request ) {
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            return new WP_Error(
                'rest_forbidden',
                __( 'You do not have permission to perform this action.', 'ai-product-tools' ),
                [ 'status' => 403 ]
            );
        }

        $nonce = $request instanceof WP_REST_Request ? $request->get_header( 'X-WP-Nonce' ) : '';
        if ( empty( $nonce ) && isset( $_REQUEST['_wpnonce'] ) ) {
            $nonce = sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) );
        }

        if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
            return new WP_Error(
                'rest_invalid_nonce',
                __( 'Invalid or missing security nonce.', 'ai-product-tools' ),
                [ 'status' => 403 ]
            );
        }

        return true;
    }

    /**
     * Handle GET request — return all current settings merged with defaults.
     *
     * Response shape matches the FAQDisplaySettingsResponse TypeScript interface:
     * { success: true, settings: FAQDisplaySettings, defaults: FAQDisplaySettings }
     *
     * @param WP_REST_Request $request Incoming REST request.
     * @return WP_REST_Response|WP_Error Response containing settings and defaults.
     */
    public function get_settings( WP_REST_Request $request ) {
        try {
            $all      = $this->faq_display_settings->getAll();
            $defaults = $this->faq_display_settings->getDefaults();

            return new WP_REST_Response( [
                'success'  => true,
                'settings' => $all,
                'defaults' => $defaults,
            ], 200 );

        } catch ( \Exception $e ) {
            return new WP_Error(
                'faq_display_settings_error',
                $e->getMessage(),
                [ 'status' => 500 ]
            );
        }
    }

    /**
     * Handle POST request — save FAQ display settings.
     *
     * Applies the aipt_faq_display_settings_save filter before persisting to
     * allow premium gating: free users have premium-only fields stripped by
     * the filter added in PremiumFAQService. All sanitization is delegated to
     * FAQDisplaySettings::update() internally.
     *
     * @param WP_REST_Request $request Incoming REST request containing 'settings' param.
     * @return WP_REST_Response|WP_Error Response containing the saved settings on success.
     */
    public function update_settings( WP_REST_Request $request ) {
        try {
            $settings = $request->get_param( 'settings' );

            if ( ! is_array( $settings ) ) {
                return new WP_Error(
                    'invalid_settings',
                    __( 'Settings must be an object.', 'ai-product-tools' ),
                    [ 'status' => 400 ]
                );
            }

            $free_fields       = [ 'accordion_enabled', 'theme_preset', 'display_mode', 'qa_labels_enabled', 'question_label', 'answer_label' ];
            $original_settings = $settings;
            $settings          = array_intersect_key( $settings, array_flip( $free_fields ) );

            /**
             * Filter FAQ display settings before persisting.
             *
             * Premium module hooks here to restore premium-only fields
             * (colors, typography, spacing, etc.) when a valid licence is present.
             *
             * @since 2.5.0
             *
             * @param array $settings          Settings after free-field allowlist.
             * @param array $original_settings  Original unfiltered settings from the request.
             */
            $settings = apply_filters( 'aipt_faq_display_settings_save', $settings, $original_settings );

            $this->faq_display_settings->update( $settings );

            return new WP_REST_Response( [
                'success'  => true,
                'settings' => $this->faq_display_settings->getAll(),
            ], 200 );

        } catch ( \Exception $e ) {
            return new WP_Error(
                'faq_display_settings_error',
                $e->getMessage(),
                [ 'status' => 500 ]
            );
        }
    }

    /**
     * Handle DELETE request — reset all settings to plugin defaults.
     *
     * Removes the stored option entirely and clears the in-memory cache so
     * subsequent reads via getAll() return the canonical defaults.
     *
     * @param WP_REST_Request $request Incoming REST request.
     * @return WP_REST_Response|WP_Error Response confirming reset on success.
     */
    public function reset_settings( WP_REST_Request $request ) {
        try {
            delete_option( 'aipt_faq_display_settings' );
            $this->faq_display_settings->clearCache();

            return new WP_REST_Response( [
                'success' => true,
            ], 200 );

        } catch ( \Exception $e ) {
            return new WP_Error(
                'faq_display_settings_error',
                $e->getMessage(),
                [ 'status' => 500 ]
            );
        }
    }
}
