<?php

namespace UltraguardPro\modules\api_security\ajax;

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

// phpcs:disable WordPress.Security.NonceVerification.Missing -- API Security AJAX handlers are registered through the shared protected AJAX framework.

use UltraguardPro\modules\core\AbstractAjaxHandler;
use UltraguardPro\modules\api_security\ApiSecurityEngine;
use UltraguardPro\core\DatabaseCrud;

class ApiSecurityAjax extends AbstractAjaxHandler {

    protected const NONCE = 'ultraguard_admin_nonce';

    private ?ApiSecurityEngine $engine = null;

    public function register(): void {
        $this->register_actions( [
            'ultraguard_api_create_key'             => [ $this, 'handle_create_key' ],
            'ultraguard_api_revoke_key'             => [ $this, 'handle_revoke_key' ],
            'ultraguard_api_list_keys'              => [ $this, 'handle_list_keys' ],
            'ultraguard_api_get_request_log'        => [ $this, 'handle_get_request_log' ],
            'ultraguard_api_get_stats'              => [ $this, 'handle_get_stats' ],
            'ultraguard_api_test_key'               => [ $this, 'handle_test_key' ],
            'ultraguard_api_clear_log'              => [ $this, 'handle_clear_log' ],
            'ultraguard_save_api_security_settings' => [ $this, 'handle_save_settings' ],
        ] );
    }

    public function handle_create_key(): void {
        $this->verify();
        $this->verify_cap( 'manage_options' );
        $this->require_pro_feature( 'api_security', __( 'generate managed API keys', 'ultraguard-security-suite' ) );

        $table = $this->t( 'api_keys' );
        if ( ! $table ) {
            $this->send_error( __( 'API key storage is unavailable.', 'ultraguard-security-suite' ), 500, 'table_missing' );
        }

        $generated       = $this->engine()->generate_api_key();
        $allowed_routes  = array_values( array_filter( array_map( 'trim', array_map( 'sanitize_text_field', (array) wp_unslash( $_POST['allowed_routes'] ?? [] ) ) ) ) );
        $allowed_methods = array_values( array_filter( array_map( 'sanitize_text_field', (array) wp_unslash( $_POST['allowed_methods'] ?? [] ) ) ) );
        $expires_at      = sanitize_text_field( wp_unslash( $_POST['expires_at'] ?? '' ) );

        $inserted = $table->insert( [
            'key_name'        => sanitize_text_field( wp_unslash( $_POST['key_name'] ?? __( 'New API Key', 'ultraguard-security-suite' ) ) ),
            'api_key'         => $generated['hash'],
            'key_prefix'      => $generated['prefix'],
            'user_id'         => absint( $_POST['user_id'] ?? get_current_user_id() ),
            'allowed_routes'  => ! empty( $allowed_routes ) ? wp_json_encode( $allowed_routes ) : '',
            'allowed_methods' => ! empty( $allowed_methods ) ? wp_json_encode( $allowed_methods ) : '',
            'rate_limit'      => max( 0, absint( $_POST['rate_limit'] ?? $this->plugin->settings->get_option( 'api_security_default_rate_limit', 60 ) ) ),
            'is_active'       => 1,
            'expires_at'      => $expires_at,
        ] );

        if ( ! $inserted ) {
            $this->send_error( __( 'Failed to create the API key.', 'ultraguard-security-suite' ), 500, 'create_failed' );
        }

        $this->send_success( [
            'message'       => __( 'API key created. Copy it now because it will only be shown once.', 'ultraguard-security-suite' ),
            'generated_key' => $generated['key'],
            'key_prefix'    => $generated['prefix'],
        ] );
    }

    public function handle_revoke_key(): void {
        $this->verify();
        $this->verify_cap( 'manage_options' );
        $this->require_pro_feature( 'api_security', __( 'revoke managed API keys', 'ultraguard-security-suite' ) );

        $table = $this->t( 'api_keys' );
        if ( ! $table ) {
            $this->send_error( __( 'API key storage is unavailable.', 'ultraguard-security-suite' ), 500, 'table_missing' );
        }

        $id = absint( $_POST['id'] ?? 0 );
        if ( $id <= 0 || ! $table->delete( $id ) ) {
            $this->send_error( __( 'Unable to revoke that API key.', 'ultraguard-security-suite' ), 400, 'revoke_failed' );
        }

        $this->send_success( [ 'message' => __( 'API key revoked.', 'ultraguard-security-suite' ) ] );
    }

    public function handle_list_keys(): void {
        $this->verify();
        $this->verify_cap( 'manage_options' );

        if ( ! \UltraguardPro\support\LicenseInfo::instance()->isPro() ) {
            $this->send_success( [ 'rows' => $this->preview_key_rows() ] );
        }

        $table = $this->t( 'api_keys' );
        $rows  = $table && method_exists( $table, 'get_recent_keys' ) ? $table->get_recent_keys( 100 ) : [];
        $this->send_success( [ 'rows' => $rows ] );
    }

    public function handle_get_request_log(): void {
        $this->verify();
        $this->verify_cap( 'manage_options' );

        if ( ! \UltraguardPro\support\LicenseInfo::instance()->isPro() ) {
            $page = max( 1, absint( $_POST['page'] ?? 1 ) );
            $this->send_success( [
                'rows' => $this->preview_request_log_rows(),
                'page' => $page,
            ] );
        }

        $table = $this->t( 'api_request_log' );
        $page  = max( 1, absint( $_POST['page'] ?? 1 ) );
        $limit = max( 1, min( 200, absint( $_POST['limit'] ?? 50 ) ) );
        $rows  = $table && method_exists( $table, 'get_recent_requests' ) ? $table->get_recent_requests( $limit, $page ) : [];

        $this->send_success( [
            'rows' => $rows,
            'page' => $page,
        ] );
    }

    public function handle_get_stats(): void {
        $this->verify();
        $this->verify_cap( 'manage_options' );

        if ( ! \UltraguardPro\support\LicenseInfo::instance()->isPro() ) {
            $this->send_success( $this->preview_stats() );
        }

        $this->send_success( $this->engine()->get_stats() );
    }

    public function handle_test_key(): void {
        $this->verify();
        $this->verify_cap( 'manage_options' );

        if ( ! \UltraguardPro\support\LicenseInfo::instance()->isPro() ) {
            $this->send_success( [
                'message' => __( 'Preview mode: this sample API key passes a read-only validation check. Upgrade to test live API routes and managed credentials.', 'ultraguard-security-suite' ),
                'preview' => true,
            ] );
        }

        $key     = sanitize_text_field( wp_unslash( $_POST['api_key'] ?? '' ) );
        $request = new \WP_REST_Request( 'GET', sanitize_text_field( wp_unslash( $_POST['route'] ?? '/wp/v2' ) ) );
        $request->set_header( 'authorization', 'Bearer ' . $key );

        $valid = $this->engine()->validate_api_key( $request );
        if ( is_wp_error( $valid ) ) {
            $status = (int) ( $valid->get_error_data()['status'] ?? 403 );
            $this->send_error( $valid->get_error_message(), $status, (string) $valid->get_error_code() );
        }

        $this->send_success( [ 'message' => __( 'API key is valid for this route.', 'ultraguard-security-suite' ) ] );
    }

    public function handle_clear_log(): void {
        $this->verify();
        $this->verify_cap( 'manage_options' );
        $this->require_pro_feature( 'api_security', __( 'clear the API request log', 'ultraguard-security-suite' ) );

        DatabaseCrud::delete_all( 'ultraguard_api_request_log' );

        $this->send_success( [ 'message' => __( 'API request log cleared.', 'ultraguard-security-suite' ) ] );
    }

    public function handle_save_settings(): void {
        $this->verify();
        $this->verify_cap( 'manage_options' );
        $this->require_pro_feature( 'api_security', __( 'save API security settings', 'ultraguard-security-suite' ) );

        $data = $this->sanitize_fields( (array) wp_unslash( $_POST ), [
            'api_security_enabled'            => [ 'type' => 'bool', 'default' => true ],
            'api_security_rest_mode'          => [ 'type' => 'key', 'default' => 'public' ],
            'api_security_blocked_routes'     => [ 'type' => 'textarea', 'default' => '' ],
            'api_security_allowed_routes'     => [ 'type' => 'textarea', 'default' => '' ],
            'api_security_enable_api_keys'    => [ 'type' => 'bool', 'default' => true ],
            'api_security_enable_xmlrpc'      => [ 'type' => 'bool', 'default' => true ],
            'api_security_xmlrpc_mode'        => [ 'type' => 'key', 'default' => 'allow_all' ],
            'api_security_xmlrpc_methods'     => [ 'type' => 'textarea', 'default' => '' ],
            'api_security_log_rest'           => [ 'type' => 'bool', 'default' => true ],
            'api_security_log_xmlrpc'         => [ 'type' => 'bool', 'default' => true ],
            'api_security_log_retention_days' => [ 'type' => 'int', 'default' => 7, 'min' => 1, 'max' => 90 ],
            'api_security_default_rate_limit' => [ 'type' => 'int', 'default' => 60, 'min' => 0, 'max' => 10000 ],
        ] );

        if ( ! $this->plugin->settings->save_module_settings( 'api_security', $data ) ) {
            $this->send_error( __( 'Failed to save API security settings.', 'ultraguard-security-suite' ), 500, 'save_failed' );
        }

        $this->send_success( [ 'message' => __( 'API security settings saved.', 'ultraguard-security-suite' ) ] );
    }

    private function engine(): ApiSecurityEngine {
        if ( null === $this->engine ) {
            $this->engine = new ApiSecurityEngine( $this->plugin );
        }

        return $this->engine;
    }

    private function preview_stats(): array {
        return [
            'total_api_keys'    => 4,
            'rest_requests_24h' => 1268,
            'blocked_24h'       => 37,
            'xmlrpc_calls_24h'  => 19,
        ];
    }

    private function preview_key_rows(): array {
        return [
            [
                'id'             => 101,
                'key_name'       => 'Headless Storefront',
                'key_prefix'     => 'ug_live_ab12',
                'user_id'        => 1,
                'allowed_routes' => wp_json_encode( [ '/wc/v3/orders', '/wc/v3/products' ] ),
                'rate_limit'     => 120,
                'is_active'      => 1,
                'last_used_at'   => gmdate( 'Y-m-d H:i:s', time() - HOUR_IN_SECONDS * 2 ),
            ],
            [
                'id'             => 102,
                'key_name'       => 'CRM Sync Worker',
                'key_prefix'     => 'ug_live_cd34',
                'user_id'        => 1,
                'allowed_routes' => wp_json_encode( [ '/wp/v2/users/me', '/wp/v2/posts' ] ),
                'rate_limit'     => 60,
                'is_active'      => 1,
                'last_used_at'   => gmdate( 'Y-m-d H:i:s', time() - HOUR_IN_SECONDS * 9 ),
            ],
        ];
    }

    private function preview_request_log_rows(): array {
        return [
            [
                'endpoint'      => '/wc/v3/orders',
                'method'        => 'GET',
                'auth_type'     => 'bearer',
                'ip_address'    => '34.210.18.72',
                'response_code' => 200,
                'was_blocked'   => 0,
                'created_at'    => gmdate( 'Y-m-d H:i:s', time() - 300 ),
            ],
            [
                'endpoint'      => '/wp/v2/users',
                'method'        => 'POST',
                'auth_type'     => 'none',
                'ip_address'    => '185.143.223.41',
                'response_code' => 403,
                'was_blocked'   => 1,
                'created_at'    => gmdate( 'Y-m-d H:i:s', time() - 1200 ),
            ],
            [
                'endpoint'      => 'wp.getUsersBlogs',
                'method'        => 'POST',
                'auth_type'     => 'xmlrpc',
                'ip_address'    => '103.87.212.9',
                'response_code' => 403,
                'was_blocked'   => 1,
                'created_at'    => gmdate( 'Y-m-d H:i:s', time() - 3900 ),
            ],
        ];
    }
}

// phpcs:enable
