<?php

defined( 'ABSPATH' ) or die( 'Forbidden' );

/**
 * Front-end AJAX endpoints for on-demand geo data loading.
 *
 * Extracted from SCPWOO_States_Places to keep the main class lean.
 */
class SCPWOO_Ajax {

    /** @var SCPWOO_States_Places */
    private $plugin;

    /**
     * @param SCPWOO_States_Places $plugin Main plugin instance.
     */
    public function __construct( SCPWOO_States_Places $plugin ) {
        $this->plugin = $plugin;
    }

    /**
     * Register the public AJAX hooks.
     */
    public function register_hooks(): void {
        add_action( 'wp_ajax_scpwoo_get_cities',              array( $this, 'ajax_get_cities' ) );
        add_action( 'wp_ajax_nopriv_scpwoo_get_cities',       array( $this, 'ajax_get_cities' ) );
        add_action( 'wp_ajax_scpwoo_get_neighborhoods',       array( $this, 'ajax_get_neighborhoods' ) );
        add_action( 'wp_ajax_nopriv_scpwoo_get_neighborhoods', array( $this, 'ajax_get_neighborhoods' ) );
        add_action( 'wp_ajax_scpwoo_set_degraded_mode',       array( $this, 'ajax_set_degraded_mode' ) );
        add_action( 'wp_ajax_nopriv_scpwoo_set_degraded_mode', array( $this, 'ajax_set_degraded_mode' ) );
    }

    /**
     * AJAX: return cities for a given country + state.
     *
     * Expected params: country (e.g. 'CM'), state (e.g. 'CE').
     * Returns JSON: { cities: ['Yaound&eacute;', 'Mbalmayo', ...] }
     */
    public function ajax_get_cities(): void {
        check_ajax_referer( 'scpwoo_front_nonce', 'nonce' );

        if ( $this->is_ajax_rate_limited() ) {
            SCPWOO_Audit::log_rate_limit( 'ajax_get_cities' );
            wp_send_json_error( array( 'message' => 'Rate limit exceeded' ), 429 );
        }

        $country = isset( $_GET['country'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_GET['country'] ) ) ) : '';
        $state   = isset( $_GET['state'] ) ? sanitize_text_field( wp_unslash( $_GET['state'] ) ) : '';

        if ( empty( $country ) ) {
            wp_send_json_error( array( 'message' => 'Missing country' ), 400 );
        }

        // Whitelist: only supported countries
        if ( ! $this->plugin->is_supported_country( $country ) ) {
            wp_send_json_error( array( 'message' => 'Unsupported country' ), 400 );
        }

        $places = $this->plugin->get_places( $country );

        if ( ! is_array( $places ) ) {
            wp_send_json_success( array( 'cities' => array() ) );
        }

        // If country has states, return cities for the specific state
        if ( ! empty( $state ) && isset( $places[ $state ] ) ) {
            wp_send_json_success( array( 'cities' => array_values( $places[ $state ] ) ) );
        }

        // If country has no states (flat array), return all cities
        if ( isset( $places[0] ) ) {
            wp_send_json_success( array( 'cities' => array_values( $places ) ) );
        }

        wp_send_json_success( array( 'cities' => array() ) );
    }

    /**
     * AJAX: return neighborhoods for a given country + city.
     *
     * Expected params: country (e.g. 'CM'), city (e.g. 'Yaound&eacute;').
     * Returns JSON: { neighborhoods: ['Bastos', 'Melen', ...] }
     */
    public function ajax_get_neighborhoods(): void {
        check_ajax_referer( 'scpwoo_front_nonce', 'nonce' );

        if ( $this->is_ajax_rate_limited() ) {
            SCPWOO_Audit::log_rate_limit( 'ajax_get_neighborhoods' );
            wp_send_json_error( array( 'message' => 'Rate limit exceeded' ), 429 );
        }

        $country = isset( $_GET['country'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_GET['country'] ) ) ) : '';
        $city    = isset( $_GET['city'] ) ? sanitize_text_field( wp_unslash( $_GET['city'] ) ) : '';

        if ( empty( $country ) || empty( $city ) ) {
            wp_send_json_error( array( 'message' => 'Missing country or city' ), 400 );
        }

        // Whitelist: only supported countries
        if ( ! $this->plugin->is_supported_country( $country ) ) {
            wp_send_json_error( array( 'message' => 'Unsupported country' ), 400 );
        }

        // Resolve city alias before looking up neighborhoods
        $city = SCPWOO_Aliases::resolve_city( $city, $country );

        $neighborhoods = $this->plugin->get_neighborhoods( $country );

        if ( is_array( $neighborhoods ) && isset( $neighborhoods[ $city ] ) ) {
            wp_send_json_success( array( 'neighborhoods' => array_values( $neighborhoods[ $city ] ) ) );
        }

        wp_send_json_success( array( 'neighborhoods' => array() ) );
    }

    /**
     * Simple IP-based rate limiter for public AJAX endpoints.
     *
     * @param int $max_requests Max requests per window.
     * @param int $window_seconds Time window in seconds.
     * @return bool True if rate limited.
     */
    private function is_ajax_rate_limited( $max_requests = 60, $window_seconds = 60 ): bool {
        $ip  = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
        $ua  = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '';
        $key = 'scpwoo_rl_' . md5( $ip . '|' . $ua );

        $data = get_transient( $key );
        if ( $data === false ) {
            set_transient( $key, 1, $window_seconds );
            return false;
        }

        if ( (int) $data >= $max_requests ) {
            return true;
        }

        set_transient( $key, (int) $data + 1, $window_seconds );
        return false;
    }

    /**
     * AJAX: store degraded-mode flag in WC session (never trust POST directly).
     */
    public function ajax_set_degraded_mode(): void {
        check_ajax_referer( 'scpwoo_front_nonce', 'nonce' );

        if ( ! function_exists( 'WC' ) || ! WC()->session ) {
            wp_send_json_error( array( 'message' => 'Session unavailable' ), 503 );
            return;
        }

        $reason = isset( $_POST['reason'] ) ? sanitize_text_field( wp_unslash( $_POST['reason'] ) ) : 'unknown';
        SCPWOO_Audit::log( 'warning', 'degraded_mode_activated', 'Degraded mode activated by client. Reason: ' . $reason );

        WC()->session->set( 'scpwoo_degraded_mode', true );
        wp_send_json_success();
    }
}
