<?php
/**
 * Admin page: Geographic data (regions, cities, neighborhoods)
 *
 * Handles the regions accordion display and AJAX operations
 * to add/delete cities and neighborhoods.
 *
 * @package AfriRegions
 */

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

class SCPWOO_Page_Geodata {

    // =========================================================================
    // Page rendering
    // =========================================================================

    /**
     * Render the "Geographic Data" page
     */
    /** @return void */
    public function render(): void {
        $states_by_country = SCPWOO_Geo_Repository::get_states_by_country();
        $places_by_country = SCPWOO_Geo_Repository::get_merged_places_by_country();
        $wc_countries      = function_exists( 'WC' ) && WC()->countries ? WC()->countries->get_countries() : array();
        $multi_country     = count( $states_by_country ) > 1;

        ?>
        <div class="scpwoo-admin-wrap">

            <div class="scpwoo-search-bar">
                <span class="dashicons dashicons-search"></span>
                <input type="text" id="scpwoo-geodata-search" placeholder="<?php esc_attr_e( 'Search regions, cities...', 'afriregions-city-neighborhood-for-woocommerce' ); ?>" aria-label="<?php esc_attr_e( 'Search regions and cities', 'afriregions-city-neighborhood-for-woocommerce' ); ?>" />
                <?php if ( $multi_country ) : ?>
                <select id="scpwoo-country-select" class="scpwoo-country-select" data-storage-key="scpwoo_geodata_country" data-target=".scpwoo-country-group" data-match="data-country">
                    <option value=""><?php esc_html_e( 'All countries', 'afriregions-city-neighborhood-for-woocommerce' ); ?></option>
                    <?php foreach ( $states_by_country as $cc => $regions ) :
                        $cn = isset( $wc_countries[ $cc ] ) ? $wc_countries[ $cc ] : $cc;
                    ?>
                        <option value="<?php echo esc_attr( $cc ); ?>"><?php echo esc_html( $cn ); ?></option>
                    <?php endforeach; ?>
                </select>
                <?php endif; ?>
            </div>

            <?php if ( count( $states_by_country ) > 0 ) : ?>
            <div class="scpwoo-map-strip" id="scpwoo-country-strip">
                <?php foreach ( $states_by_country as $cc => $regions ) :
                    $cn = isset( $wc_countries[ $cc ] ) ? $wc_countries[ $cc ] : $cc;
                ?>
                <button type="button" class="scpwoo-map-btn" data-country="<?php echo esc_attr( $cc ); ?>">
                    <span class="scpwoo-cc"><?php echo esc_html( $cc ); ?></span>
                    <?php echo esc_html( $cn ); ?>
                </button>
                <?php endforeach; ?>
            </div>
            <?php endif; ?>

            <div class="scpwoo-regions-accordion">
                <?php foreach ( $states_by_country as $country_code => $regions ) :
                    $country_name = isset( $wc_countries[ $country_code ] ) ? $wc_countries[ $country_code ] : $country_code;
                    $country_places = isset( $places_by_country[ $country_code ] ) ? $places_by_country[ $country_code ] : array();
                ?>
                    <?php if ( $multi_country ) : ?>
                    <div class="scpwoo-country-group">
                        <h3 class="scpwoo-country-heading"><?php echo esc_html( $country_name ); ?> <span class="scpwoo-country-code">(<?php echo esc_html( $country_code ); ?>)</span></h3>
                    <?php endif; ?>
                    <?php foreach ( $regions as $code => $name ) :
                        $city_count = isset( $country_places[ $code ] ) ? count( $country_places[ $code ] ) : 0;
                    ?>
                    <div class="scpwoo-region" data-region="<?php echo esc_attr( $code ); ?>" data-country="<?php echo esc_attr( $country_code ); ?>">
                        <div class="scpwoo-region-header" role="button" tabindex="0" aria-expanded="false" aria-controls="scpwoo-region-body-<?php echo esc_attr( $country_code . '-' . $code ); ?>">
                            <span class="dashicons dashicons-arrow-right-alt2 scpwoo-toggle-icon" aria-hidden="true"></span>
                            <strong><?php echo esc_html( $name ); ?></strong>
                            <span class="scpwoo-region-code">(<?php echo esc_html( $code ); ?>)</span>
                            <span class="scpwoo-count"><?php echo esc_html( $city_count ); ?> <?php esc_html_e( 'cities', 'afriregions-city-neighborhood-for-woocommerce' ); ?></span>
                        </div>
                        <div class="scpwoo-region-body scpwoo-hidden" id="scpwoo-region-body-<?php echo esc_attr( $country_code . '-' . $code ); ?>">
                            <p class="scpwoo-loading"><?php esc_html_e( 'Loading...', 'afriregions-city-neighborhood-for-woocommerce' ); ?></p>
                        </div>
                    </div>
                    <?php endforeach; ?>
                    <?php if ( $multi_country ) : ?>
                    </div>
                    <?php endif; ?>
                <?php endforeach; ?>
            </div>
        </div>
        <?php
    }

    // =========================================================================
    // AJAX Handlers
    // =========================================================================

    /**
     * AJAX: Get region data (cities + neighborhoods)
     *
     * Expects POST: nonce, region_code, country_code.
     */
    /** @return void */
    public function ajax_get_region_data(): void {
        check_ajax_referer( SCPWOO_States_Places::NONCE_ADMIN, 'nonce' );

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( array( 'message' => 'Permission denied' ) );
        }

        $region_code  = sanitize_text_field( wp_unslash( $_POST['region_code'] ?? '' ) );
        $country_code = strtoupper( sanitize_text_field( wp_unslash( $_POST['country_code'] ?? '' ) ) );

        if ( empty( $region_code ) ) {
            wp_send_json_error( array( 'message' => 'Region code required' ) );
        }

        // If no country provided, try to find it
        if ( empty( $country_code ) ) {
            $country_code = SCPWOO_Geo_Repository::find_country_for_region( $region_code );
        }

        // Whitelist: country must be known
        if ( ! SCPWOO_Geo_Repository::is_valid_country( $country_code ) ) {
            wp_send_json_error( array( 'message' => 'Invalid country code' ), 400 );
        }

        // Validate: region must belong to country
        if ( ! SCPWOO_Geo_Repository::is_valid_region( $country_code, $region_code ) ) {
            wp_send_json_error( array( 'message' => 'Invalid region code for this country' ), 400 );
        }

        $places_by_country  = SCPWOO_Geo_Repository::get_merged_places_by_country();
        $default_places_bc  = SCPWOO_Geo_Repository::get_places_by_country();
        $hoods_by_country   = SCPWOO_Geo_Repository::get_merged_neighborhoods_by_country();
        $default_hoods_bc   = SCPWOO_Geo_Repository::get_neighborhoods_by_country();

        $country_places     = isset( $places_by_country[ $country_code ] ) ? $places_by_country[ $country_code ] : array();
        $country_def_places = isset( $default_places_bc[ $country_code ] ) ? $default_places_bc[ $country_code ] : array();
        $country_hoods      = isset( $hoods_by_country[ $country_code ] ) ? $hoods_by_country[ $country_code ] : array();
        $country_def_hoods  = isset( $default_hoods_bc[ $country_code ] ) ? $default_hoods_bc[ $country_code ] : array();

        $cities         = isset( $country_places[ $region_code ] ) ? $country_places[ $region_code ] : array();
        $default_cities = isset( $country_def_places[ $region_code ] ) ? $country_def_places[ $region_code ] : array();

        $data = array();
        foreach ( $cities as $city ) {
            $city_neighborhoods = isset( $country_hoods[ $city ] ) ? $country_hoods[ $city ] : array();
            $city_default_hoods = isset( $country_def_hoods[ $city ] ) ? $country_def_hoods[ $city ] : array();

            $hoods_data = array();
            foreach ( $city_neighborhoods as $hood ) {
                $hoods_data[] = array(
                    'name'   => $hood,
                    'source' => SCPWOO_Geo_Repository::get_item_source( $hood, $city_default_hoods ),
                );
            }

            $data[] = array(
                'name'          => $city,
                'source'        => SCPWOO_Geo_Repository::get_item_source( $city, $default_cities ),
                'neighborhoods' => $hoods_data,
            );
        }

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

    /**
     * AJAX: Add a city to a region
     *
     * Expects POST: nonce, region_code, city_name, country_code.
     */
    /** @return void */
    public function ajax_add_city(): void {
        check_ajax_referer( SCPWOO_States_Places::NONCE_ADMIN_WRITE, 'nonce' );

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( array( 'message' => 'Permission denied' ) );
        }

        $region_code  = sanitize_text_field( wp_unslash( $_POST['region_code'] ?? '' ) );
        $city_name    = sanitize_text_field( wp_unslash( $_POST['city_name'] ?? '' ) );
        $country_code = strtoupper( sanitize_text_field( wp_unslash( $_POST['country_code'] ?? '' ) ) );

        if ( empty( $region_code ) || empty( $city_name ) ) {
            wp_send_json_error( array( 'message' => 'Region and city name required' ) );
        }

        // Max length
        if ( mb_strlen( $city_name ) > SCPWOO_States_Places::MAX_LEN_CITY ) {
            wp_send_json_error( array( 'message' => 'City name too long' ), 400 );
        }

        if ( empty( $country_code ) ) {
            $country_code = SCPWOO_Geo_Repository::find_country_for_region( $region_code );
        }

        // Whitelist: country must be known
        if ( ! SCPWOO_Geo_Repository::is_valid_country( $country_code ) ) {
            wp_send_json_error( array( 'message' => 'Invalid country code' ), 400 );
        }

        // Validate: region must belong to country
        if ( ! SCPWOO_Geo_Repository::is_valid_region( $country_code, $region_code ) ) {
            wp_send_json_error( array( 'message' => 'Invalid region code for this country' ), 400 );
        }

        if ( ! SCPWOO_Geo_Repository::add_city( $country_code, $region_code, $city_name ) ) {
            wp_send_json_error( array(
                'message' => __( 'This city already exists.', 'afriregions-city-neighborhood-for-woocommerce' ),
            ) );
        }

        // Determine source of the just-added/restored city
        global $wpdb;
        $source = $wpdb->get_var( $wpdb->prepare(
            "SELECT source FROM " . SCPWOO_Geo_Repository::get_table_name() . " WHERE country_code = %s AND region_code = %s AND type = 'city' AND name = %s AND is_deleted = 0",
            $country_code, $region_code, $city_name
        ) );

        SCPWOO_Audit::log_geo_change( 'add_city', $country_code, array( 'region' => $region_code, 'city' => $city_name ) );
        wp_send_json_success( array( 'source' => $source ?: 'custom' ) );
    }

    /**
     * AJAX: Delete a city from a region
     *
     * Expects POST: nonce, region_code, city_name, country_code.
     */
    /** @return void */
    public function ajax_delete_city(): void {
        check_ajax_referer( SCPWOO_States_Places::NONCE_ADMIN_WRITE, 'nonce' );

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( array( 'message' => 'Permission denied' ) );
        }

        $region_code  = sanitize_text_field( wp_unslash( $_POST['region_code'] ?? '' ) );
        $city_name    = sanitize_text_field( wp_unslash( $_POST['city_name'] ?? '' ) );
        $country_code = strtoupper( sanitize_text_field( wp_unslash( $_POST['country_code'] ?? '' ) ) );

        if ( empty( $region_code ) || empty( $city_name ) ) {
            wp_send_json_error( array( 'message' => 'Region and city name required' ) );
        }

        if ( empty( $country_code ) ) {
            $country_code = SCPWOO_Geo_Repository::find_country_for_region( $region_code );
        }

        // Whitelist: country must be known
        if ( ! SCPWOO_Geo_Repository::is_valid_country( $country_code ) ) {
            wp_send_json_error( array( 'message' => 'Invalid country code' ), 400 );
        }

        // Validate: region must belong to country
        if ( ! SCPWOO_Geo_Repository::is_valid_region( $country_code, $region_code ) ) {
            wp_send_json_error( array( 'message' => 'Invalid region code for this country' ), 400 );
        }

        SCPWOO_Geo_Repository::delete_city( $country_code, $region_code, $city_name );

        SCPWOO_Audit::log_geo_change( 'delete_city', $country_code, array( 'region' => $region_code, 'city' => $city_name ) );
        wp_send_json_success();
    }

    /**
     * AJAX: Add a neighborhood to a city
     *
     * Expects POST: nonce, city_name, neighborhood_name, country_code.
     */
    /** @return void */
    public function ajax_add_neighborhood(): void {
        check_ajax_referer( SCPWOO_States_Places::NONCE_ADMIN_WRITE, 'nonce' );

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( array( 'message' => 'Permission denied' ) );
        }

        $city_name         = sanitize_text_field( wp_unslash( $_POST['city_name'] ?? '' ) );
        $neighborhood_name = sanitize_text_field( wp_unslash( $_POST['neighborhood_name'] ?? '' ) );
        $country_code      = strtoupper( sanitize_text_field( wp_unslash( $_POST['country_code'] ?? '' ) ) );

        if ( empty( $city_name ) || empty( $neighborhood_name ) ) {
            wp_send_json_error( array( 'message' => 'City and neighborhood name required' ) );
        }

        // Max length
        if ( mb_strlen( $neighborhood_name ) > SCPWOO_States_Places::MAX_LEN_NEIGHBORHOOD ) {
            wp_send_json_error( array( 'message' => 'Neighborhood name too long' ), 400 );
        }

        if ( empty( $country_code ) ) {
            $country_code = SCPWOO_Geo_Repository::find_country_for_city( $city_name );
        }

        // Whitelist: country must be known
        if ( ! SCPWOO_Geo_Repository::is_valid_country( $country_code ) ) {
            wp_send_json_error( array( 'message' => 'Invalid country code' ), 400 );
        }

        // Validate hierarchy: city must belong to this country
        if ( ! SCPWOO_Geo_Repository::is_valid_city_in_country( $country_code, $city_name ) ) {
            wp_send_json_error( array( 'message' => 'City does not belong to this country' ), 400 );
        }

        if ( ! SCPWOO_Geo_Repository::add_neighborhood( $country_code, $city_name, $neighborhood_name ) ) {
            wp_send_json_error( array(
                'message' => __( 'This neighborhood already exists.', 'afriregions-city-neighborhood-for-woocommerce' ),
            ) );
        }

        // Determine source of the just-added/restored neighborhood
        global $wpdb;
        $source = $wpdb->get_var( $wpdb->prepare(
            "SELECT source FROM " . SCPWOO_Geo_Repository::get_table_name() . " WHERE country_code = %s AND type = 'neighborhood' AND name = %s AND parent_name = %s AND is_deleted = 0",
            $country_code, $neighborhood_name, $city_name
        ) );

        SCPWOO_Audit::log_geo_change( 'add_neighborhood', $country_code, array( 'city' => $city_name, 'neighborhood' => $neighborhood_name ) );
        wp_send_json_success( array( 'source' => $source ?: 'custom' ) );
    }

    /**
     * AJAX: Delete a neighborhood from a city
     *
     * Expects POST: nonce, city_name, neighborhood_name, country_code.
     */
    /** @return void */
    public function ajax_delete_neighborhood(): void {
        check_ajax_referer( SCPWOO_States_Places::NONCE_ADMIN_WRITE, 'nonce' );

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( array( 'message' => 'Permission denied' ) );
        }

        $city_name         = sanitize_text_field( wp_unslash( $_POST['city_name'] ?? '' ) );
        $neighborhood_name = sanitize_text_field( wp_unslash( $_POST['neighborhood_name'] ?? '' ) );
        $country_code      = strtoupper( sanitize_text_field( wp_unslash( $_POST['country_code'] ?? '' ) ) );

        if ( empty( $city_name ) || empty( $neighborhood_name ) ) {
            wp_send_json_error( array( 'message' => 'City and neighborhood name required' ) );
        }

        if ( empty( $country_code ) ) {
            $country_code = SCPWOO_Geo_Repository::find_country_for_city( $city_name );
        }

        // Whitelist: country must be known
        if ( ! SCPWOO_Geo_Repository::is_valid_country( $country_code ) ) {
            wp_send_json_error( array( 'message' => 'Invalid country code' ), 400 );
        }

        // Validate hierarchy: city must belong to this country
        if ( ! SCPWOO_Geo_Repository::is_valid_city_in_country( $country_code, $city_name ) ) {
            wp_send_json_error( array( 'message' => 'City does not belong to this country' ), 400 );
        }

        SCPWOO_Geo_Repository::delete_neighborhood( $country_code, $city_name, $neighborhood_name );

        SCPWOO_Audit::log_geo_change( 'delete_neighborhood', $country_code, array( 'city' => $city_name, 'neighborhood' => $neighborhood_name ) );
        wp_send_json_success();
    }
}
