<?php
if ( ! defined( 'ABSPATH' ) ) exit;
class IntegratePalace_Properties_Webhooks {

    public static function init() {
        add_action('rest_api_init', array(__CLASS__, 'register_routes'));
    }

    public static function register_routes() {
        $blog_id = get_option("integrate_palace-palace-unique-id");
        $webhook_url = "/webhook/$blog_id";
        register_rest_route('integrate-palace-properties/v1', $webhook_url, array(
            'methods' => 'POST',
            'callback' => array(__CLASS__, 'handle_webhook'),
            'permission_callback' => array(__CLASS__, 'verify_webhook_signature'),
        ));
    }

    /**
     * Verify HMAC signature on incoming webhook requests.
     */
    public static function verify_webhook_signature( WP_REST_Request $request ) {
        $secret = get_option( 'integrate_palace_webhook_secret', '' );

        // No secret configured — allow all requests for backwards compatibility
        if ( empty( $secret ) ) {
            return true;
        }

        $signature = $request->get_header('X-Palace-Signature');
        if ( empty( $signature ) ) {
            return new \WP_Error(
                'rest_forbidden',
                __( 'Missing webhook signature.', 'integrate-palace-properties' ),
                array( 'status' => 403 )
            );
        }

        $body = $request->get_body();
        $expected = hash_hmac( 'sha256', $body, $secret );

        if ( ! hash_equals( $expected, $signature ) ) {
            return new \WP_Error(
                'rest_forbidden',
                __( 'Invalid webhook signature.', 'integrate-palace-properties' ),
                array( 'status' => 403 )
            );
        }

        return true;
    }

    /**
     * Helper: safely get nested array value.
     */
    private static function arr_get( $array, $key, $default = '' ) {
        $keys = explode( '.', $key );
        foreach ( $keys as $k ) {
            if ( ! is_array( $array ) || ! array_key_exists( $k, $array ) ) {
                return $default;
            }
            $array = $array[ $k ];
        }
        return $array;
    }

    private static function get_property_id_by_code($property_code) {
        $cache_key = 'property_id_' . $property_code;
        $post_id = wp_cache_get($cache_key, 'property_cache');

        if ($post_id === false) {
            $args = [
                'post_type'      => 'palace-properties',
                'meta_key'       => 'ipp_property_code',
                'meta_value'     => $property_code,
                'fields'         => 'ids',
                'posts_per_page' => 1,
                'post_status'    => 'any',
            ];

            $posts = get_posts($args);

            // Fallback: check legacy meta key for backward compatibility
            if ( empty( $posts ) ) {
                $args['meta_key'] = 'information_property_code';
                $posts = get_posts($args);
            }

            $post_id = !empty($posts) ? $posts[0] : null;
            if ($post_id) {
                wp_cache_set($cache_key, $post_id, 'property_cache', 3600);
            }
        }

        return $post_id;
    }

    private static function delete_property($property_code) {
        $property_code = sanitize_text_field($property_code);
        if (!$property_code) {
            return new WP_REST_Response(['status' => 'error', 'message' => 'Property code does not exist'], 404);
        }

        $post_id = self::get_property_id_by_code($property_code);

        if ($post_id) {
            /** @hook ipp_before_property_delete — Fires before a property is deleted via webhook. */
            do_action( 'ipp_before_property_delete', $post_id, $property_code );
        }

        if ($post_id && wp_delete_post($post_id, false)) {
            $gallery_images = get_post_meta($post_id, 'integrate_palace_gallery', true);
            if (!empty($gallery_images) && is_array($gallery_images)) {
                foreach ($gallery_images as $image_id) {
                    wp_delete_attachment(intval($image_id), true);
                }
            }
            delete_post_thumbnail($post_id);
            wp_cache_delete('property_id_' . $property_code, 'property_cache');

            /** @hook ipp_after_property_delete — Fires after a property is deleted via webhook. */
            do_action( 'ipp_after_property_delete', $post_id, $property_code );

            // Update last sync time
            update_option( 'ipp_last_sync_time', current_time( 'mysql' ), false );

            return new WP_REST_Response(['status' => 'success', 'message' => 'Property deleted successfully'], 200);
        }

        return new WP_REST_Response(
            ['status' => 'error', 'message' => $post_id ? 'Failed to delete property' : 'Property not found'],
            $post_id ? 500 : 404
        );
    }

    public static function handle_webhook(WP_REST_Request $request) {
        $property = $request->get_json_params();

        // Handle delete action
        if (!empty($property['PropertyCode']) && isset($property['action']) && $property['action'] === 'delete') {
            return self::delete_property($property['PropertyCode']);
        }

        if (!isset($property['PropertyCode'])) {
            return new WP_REST_Response(array('status' => 'error', 'message' => 'Missing required fields'), 400);
        }

        $property = apply_filters('before_insert_palace_property', $property);
        $show_on_website = apply_filters('show_on_website_palace_property', true, $property);
        if (!$show_on_website) {
            return self::delete_property($property['PropertyCode']);
        }

        $property_code = sanitize_text_field($property['PropertyCode']);

        // Invalidate cache
        wp_cache_delete('property_id_' . $property_code, 'property_cache');

        // Check if property is locked (prevent webhook from overwriting)
        $existing_id = self::get_property_id_by_code($property_code);
        if ( $existing_id && get_post_meta( $existing_id, 'ipp_lock_updates', true ) === '1' ) {
            return new WP_REST_Response( array( 'status' => 'success', 'message' => 'Property is locked, skipping update' ), 200 );
        }

        // Build post title
        $header = self::arr_get($property, 'PropertyFeatures.PropertyHeader');
        $post_title = !empty($header)
            ? sanitize_text_field($header)
            : sanitize_text_field(
                self::arr_get($property, 'PropertyAddress3') . ', ' .
                self::arr_get($property, 'PropertyAddress1') . ' ' .
                self::arr_get($property, 'PropertyAddress2')
            );
        $post_content = sanitize_textarea_field(self::arr_get($property, 'PropertyFeatures.PropertyAdvertText'));

        // Check if property exists
        $post_id = self::get_property_id_by_code($property_code);

        // Idempotency check
        if (!empty($post_id)) {
            $stored_change_code = get_post_meta($post_id, 'ipp_change_code', true);
            // Also check legacy key
            if (empty($stored_change_code)) {
                $stored_change_code = get_post_meta($post_id, 'information_code', true);
            }
            $incoming_change_code = self::arr_get($property, 'PropertyChangeCode');
            if (!empty($stored_change_code) && $stored_change_code == $incoming_change_code) {
                return new WP_REST_Response(array('status' => 'success', 'message' => 'Already up to date'), 200);
            }
        }

        /** @hook ipp_before_property_save — Fires before a property is saved/updated via webhook. */
        do_action( 'ipp_before_property_save', $post_id ?: 0, $property );

        // Create or update post
        $post_data = array(
            'post_title'   => $post_title,
            'post_content' => $post_content,
            'post_status'  => 'publish',
            'post_type'    => 'palace-properties',
        );
        if (!empty($post_id)) {
            $post_data['ID'] = $post_id;
            $post_id = wp_update_post($post_data);
        } else {
            $post_id = wp_insert_post($post_data);
        }

        if (!$post_id || is_wp_error($post_id)) {
            return new WP_REST_Response(array('status' => 'error', 'message' => 'Failed to save property'), 500);
        }

        // ─── Store ALL property fields ───────────────────────────────────

        $features = isset($property['PropertyFeatures']) && is_array($property['PropertyFeatures'])
            ? $property['PropertyFeatures'] : [];
        $agent = isset($property['PropertyPublishAgent']) && is_array($property['PropertyPublishAgent'])
            ? $property['PropertyPublishAgent']
            : (isset($property['PropertyAgent']) && is_array($property['PropertyAgent']) ? $property['PropertyAgent'] : []);
        $suburbs = isset($property['PropertySuburbs']) && is_array($property['PropertySuburbs'])
            ? $property['PropertySuburbs']
            : (isset($property['PropertySuburb']) && is_array($property['PropertySuburb']) ? $property['PropertySuburb'] : []);

        // === Core Identification ===
        update_post_meta($post_id, 'ipp_property_code', $property_code);
        update_post_meta($post_id, 'information_property_code', $property_code); // legacy compat
        update_post_meta($post_id, 'ipp_change_code', sanitize_text_field(self::arr_get($property, 'PropertyChangeCode')));
        update_post_meta($post_id, 'information_code', sanitize_text_field(self::arr_get($property, 'PropertyChangeCode'))); // legacy
        update_post_meta($post_id, 'ipp_property_code_global', sanitize_text_field(self::arr_get($property, 'PropertyCodeGlobal')));
        update_post_meta($post_id, 'ipp_our_code', sanitize_text_field(self::arr_get($property, 'PropertyOurCode')));
        update_post_meta($post_id, 'ipp_sort_code', sanitize_text_field(self::arr_get($property, 'PropertySortCode')));

        // === Status & Type ===
        update_post_meta($post_id, 'ipp_status', sanitize_text_field(self::arr_get($property, 'PropertyStatus')));
        update_post_meta($post_id, 'property_status', sanitize_text_field(self::arr_get($property, 'PropertyStatus'))); // legacy
        update_post_meta($post_id, 'ipp_archived', sanitize_text_field(self::arr_get($property, 'PropertyArchived')));
        update_post_meta($post_id, 'ipp_management_type', sanitize_text_field(self::arr_get($property, 'PropertyManagementType')));
        update_post_meta($post_id, 'property_management_type', sanitize_text_field(self::arr_get($property, 'PropertyManagementType'))); // legacy

        // === Address ===
        $addr1 = sanitize_text_field(self::arr_get($property, 'PropertyAddress1'));
        $addr2 = sanitize_text_field(self::arr_get($property, 'PropertyAddress2'));
        $addr3 = sanitize_text_field(self::arr_get($property, 'PropertyAddress3'));
        $addr4 = sanitize_text_field(self::arr_get($property, 'PropertyAddress4'));
        update_post_meta($post_id, 'ipp_address1', $addr1);
        update_post_meta($post_id, 'ipp_address2', $addr2);
        update_post_meta($post_id, 'ipp_address3', $addr3);
        update_post_meta($post_id, 'ipp_address4', $addr4);
        update_post_meta($post_id, 'ipp_unit', sanitize_text_field(self::arr_get($property, 'PropertyUnit')));
        update_post_meta($post_id, 'ipp_postcode', sanitize_text_field(self::arr_get($property, 'PropertyPostCode', self::arr_get($features, 'PropertyPostCode'))));
        // Legacy address fields
        update_post_meta($post_id, 'information_address', "$addr1, $addr2, $addr3");
        update_post_meta($post_id, 'street_number', $addr1);
        update_post_meta($post_id, 'street_name', $addr2);
        update_post_meta($post_id, 'property_city', $addr3);
        update_post_meta($post_id, 'zipcode', sanitize_text_field(self::arr_get($property, 'PropertyPostCode')));

        // === Financial ===
        update_post_meta($post_id, 'ipp_rent_amount', sanitize_text_field(self::arr_get($property, 'PropertyRentAmount')));
        update_post_meta($post_id, 'information_rent', sanitize_text_field(self::arr_get($property, 'PropertyRentAmount'))); // legacy
        update_post_meta($post_id, 'ipp_rental_period', sanitize_text_field(self::arr_get($property, 'PropertyRentalPeriod')));
        update_post_meta($post_id, 'property_rental_period', sanitize_text_field(self::arr_get($property, 'PropertyRentalPeriod'))); // legacy
        update_post_meta($post_id, 'ipp_market_value', sanitize_text_field(self::arr_get($property, 'PropertyMarketValue')));
        update_post_meta($post_id, 'ipp_commission_percent', sanitize_text_field(self::arr_get($property, 'PropertyCommissionPercent')));
        update_post_meta($post_id, 'ipp_maintenance_fee_percent', sanitize_text_field(self::arr_get($property, 'PropertyMaintenanceFeePercent')));
        update_post_meta($post_id, 'ipp_keepback_amount', sanitize_text_field(self::arr_get($property, 'PropertyKeepBackAmount')));
        update_post_meta($post_id, 'ipp_keepback_reason', sanitize_text_field(self::arr_get($property, 'PropertyKeepBackReason')));

        // === Dates ===
        update_post_meta($post_id, 'ipp_date_available', sanitize_text_field(self::arr_get($property, 'PropertyDateAvailable')));
        update_post_meta($post_id, 'information_date', sanitize_text_field(self::arr_get($property, 'PropertyDateAvailable'))); // legacy
        update_post_meta($post_id, 'ipp_start_date', sanitize_text_field(self::arr_get($property, 'PropertyStartDate')));

        // === Features (from PropertyFeatures object) ===
        update_post_meta($post_id, 'ipp_bedrooms', sanitize_text_field(self::arr_get($features, 'PropertyBedroomsNo')));
        update_post_meta($post_id, 'accommodation_bed_room', sanitize_text_field(self::arr_get($features, 'PropertyBedroomsNo'))); // legacy
        update_post_meta($post_id, 'ipp_bathrooms', sanitize_text_field(self::arr_get($features, 'PropertyBathroomsNo')));
        update_post_meta($post_id, 'accommodation_bath_room', sanitize_text_field(self::arr_get($features, 'PropertyBathroomsNo'))); // legacy
        update_post_meta($post_id, 'ipp_ensuites', sanitize_text_field(self::arr_get($features, 'PropertyEnsuitesNo')));
        update_post_meta($post_id, 'ipp_cars', sanitize_text_field(self::arr_get($features, 'PropertyCarsNo')));
        update_post_meta($post_id, 'accommodation_automobile', sanitize_text_field(self::arr_get($features, 'PropertyCarsNo'))); // legacy
        update_post_meta($post_id, 'ipp_parking', sanitize_text_field(self::arr_get($features, 'PropertyParking')));
        update_post_meta($post_id, 'other_parking', sanitize_text_field(self::arr_get($features, 'PropertyParking'))); // legacy
        update_post_meta($post_id, 'ipp_pets_allowed', self::arr_get($features, 'PropertyPetsAllowed') === 'Yes' ? '1' : '0');
        update_post_meta($post_id, 'other_pets', self::arr_get($features, 'PropertyPetsAllowed') === 'Yes' ? '1' : '0'); // legacy
        update_post_meta($post_id, 'ipp_smokers_allowed', self::arr_get($features, 'PropertySmokersAllowed') === 'Yes' ? '1' : '0');
        update_post_meta($post_id, 'property_smokers_allowed', self::arr_get($features, 'PropertySmokersAllowed') === 'Yes' ? '1' : '0'); // legacy
        update_post_meta($post_id, 'ipp_class', sanitize_text_field(self::arr_get($features, 'PropertyClass')));
        update_post_meta($post_id, 'property_class', sanitize_text_field(self::arr_get($features, 'PropertyClass'))); // legacy
        update_post_meta($post_id, 'ipp_year_built', sanitize_text_field(self::arr_get($features, 'PropertyYearBuilt')));
        update_post_meta($post_id, 'property_year_built', sanitize_text_field(self::arr_get($features, 'PropertyYearBuilt'))); // legacy
        update_post_meta($post_id, 'ipp_stories', sanitize_text_field(self::arr_get($features, 'PropertyStories')));
        update_post_meta($post_id, 'ipp_furnishings', sanitize_text_field(self::arr_get($features, 'PropertyFurnishings')));
        update_post_meta($post_id, 'ipp_new_construction', sanitize_text_field(self::arr_get($features, 'PropertyNewConstruction')));
        update_post_meta($post_id, 'ipp_amenities', sanitize_text_field(self::arr_get($features, 'PropertyAmenities')));

        // === Area & Land ===
        update_post_meta($post_id, 'ipp_floor_area', sanitize_text_field(self::arr_get($features, 'PropertyFloorArea')));
        update_post_meta($post_id, 'ipp_land_area_sqm', sanitize_text_field(self::arr_get($features, 'PropertyLandAreaMSquared')));
        update_post_meta($post_id, 'ipp_land_area_hectares', sanitize_text_field(self::arr_get($features, 'PropertyLandAreaHectares')));
        // Legacy: best available area
        $area = self::arr_get($features, 'PropertyLandAreaMSquared') ?: self::arr_get($features, 'PropertyFloorArea');
        if ($area) {
            update_post_meta($post_id, 'property_area', sanitize_text_field($area));
        }

        // === Online / Links ===
        update_post_meta($post_id, 'ipp_virtual_tour_url', esc_url_raw(self::arr_get($features, 'PropertyVirtualTourURL')));
        update_post_meta($post_id, 'property_virtual_tour_url', esc_url_raw(self::arr_get($features, 'PropertyVirtualTourURL'))); // legacy
        update_post_meta($post_id, 'ipp_web_link_url', esc_url_raw(self::arr_get($features, 'PropertyWebLinkURL')));
        update_post_meta($post_id, 'ipp_geographic_location', sanitize_text_field(self::arr_get($features, 'PropertyGeographicLocation')));
        update_post_meta($post_id, 'property_geographic_location', sanitize_text_field(self::arr_get($features, 'PropertyGeographicLocation'))); // legacy

        // === Publish settings ===
        update_post_meta($post_id, 'ipp_publish_address', sanitize_text_field(self::arr_get($features, 'PropertyPublishAddress')));
        update_post_meta($post_id, 'ipp_publish_entry', sanitize_text_field(self::arr_get($features, 'PropertyPublishEntry')));
        update_post_meta($post_id, 'ipp_header', sanitize_text_field(self::arr_get($features, 'PropertyHeader')));
        update_post_meta($post_id, 'ipp_advert_text', sanitize_textarea_field(self::arr_get($features, 'PropertyAdvertText')));
        update_post_meta($post_id, 'ipp_feature_details', sanitize_textarea_field(self::arr_get($features, 'PropertyFeatureDetails')));

        // === Property Details ===
        update_post_meta($post_id, 'ipp_name', sanitize_text_field(self::arr_get($property, 'PropertyName')));
        update_post_meta($post_id, 'ipp_phone', sanitize_text_field(self::arr_get($property, 'PropertyPhone')));
        update_post_meta($post_id, 'ipp_notes', wp_kses_post(self::arr_get($property, 'PropertyNotes')));
        update_post_meta($post_id, 'ipp_key_no', sanitize_text_field(self::arr_get($property, 'PropertyKeyNo')));
        update_post_meta($post_id, 'ipp_key_access', sanitize_text_field(self::arr_get($property, 'PropertyKeyAccess')));
        update_post_meta($post_id, 'ipp_owner_code', sanitize_text_field(self::arr_get($property, 'PropertyOwnerCode')));
        update_post_meta($post_id, 'property_owner_code', sanitize_text_field(self::arr_get($property, 'PropertyOwnerCode'))); // legacy
        update_post_meta($post_id, 'ipp_la_account_no', sanitize_text_field(self::arr_get($property, 'PropertyLAAccountNo')));
        update_post_meta($post_id, 'ipp_grid', sanitize_text_field(self::arr_get($property, 'PropertyGrid')));

        // === Agent (from PropertyPublishAgent or PropertyAgent) ===
        update_post_meta($post_id, 'ipp_agent_code', sanitize_text_field(self::arr_get($agent, 'PropertyAgentCode')));
        update_post_meta($post_id, 'agent_code', sanitize_text_field(self::arr_get($agent, 'PropertyAgentCode'))); // legacy
        update_post_meta($post_id, 'ipp_agent_full_name', sanitize_text_field(self::arr_get($agent, 'PropertyAgentFullName')));
        update_post_meta($post_id, 'agent_full_name', sanitize_text_field(self::arr_get($agent, 'PropertyAgentFullName'))); // legacy
        update_post_meta($post_id, 'ipp_agent_title', sanitize_text_field(self::arr_get($agent, 'PropertyAgentTitle')));
        update_post_meta($post_id, 'agent_title', sanitize_text_field(self::arr_get($agent, 'PropertyAgentTitle'))); // legacy
        update_post_meta($post_id, 'ipp_agent_email1', sanitize_email(self::arr_get($agent, 'PropertyAgentEmail1')));
        update_post_meta($post_id, 'agent_email1', sanitize_email(self::arr_get($agent, 'PropertyAgentEmail1'))); // legacy
        update_post_meta($post_id, 'ipp_agent_email2', sanitize_email(self::arr_get($agent, 'PropertyAgentEmail2')));
        update_post_meta($post_id, 'agent_email2', sanitize_email(self::arr_get($agent, 'PropertyAgentEmail2'))); // legacy
        update_post_meta($post_id, 'ipp_agent_phone_mobile', sanitize_text_field(self::arr_get($agent, 'PropertyAgentPhoneMobile')));
        update_post_meta($post_id, 'agent_phone_mobile', sanitize_text_field(self::arr_get($agent, 'PropertyAgentPhoneMobile'))); // legacy
        update_post_meta($post_id, 'ipp_agent_phone_work', sanitize_text_field(self::arr_get($agent, 'PropertyAgentPhoneWork')));
        update_post_meta($post_id, 'agent_phone_work', sanitize_text_field(self::arr_get($agent, 'PropertyAgentPhoneWork'))); // legacy
        update_post_meta($post_id, 'ipp_agent_fax', sanitize_text_field(self::arr_get($agent, 'PropertyAgentFax')));
        update_post_meta($post_id, 'agent_fax', sanitize_text_field(self::arr_get($agent, 'PropertyAgentFax'))); // legacy
        update_post_meta($post_id, 'ipp_agent_external_codes', sanitize_text_field(self::arr_get($agent, 'PropertyExternalCodes')));

        // === Suburbs ===
        $primary_suburb = '';
        $primary_region = '';
        if (!empty($suburbs)) {
            update_post_meta($post_id, 'ipp_suburbs', wp_json_encode($suburbs));
            foreach ($suburbs as $index => $suburb) {
                if (!is_array($suburb)) continue;
                $sname = sanitize_text_field($suburb['PropertySuburbName'] ?? '');
                $sregion = sanitize_text_field($suburb['PropertySuburbRegionOrState'] ?? '');
                $scode = sanitize_text_field($suburb['PropertySuburbCode'] ?? '');
                $sdistrict = sanitize_text_field($suburb['PropertySuburbDistrictOrPostcode'] ?? '');
                $stype = sanitize_text_field($suburb['PropertySuburbType'] ?? '');

                update_post_meta($post_id, 'property_suburb_code_' . $index, $scode);
                update_post_meta($post_id, 'property_suburb_district_' . $index, $sdistrict);
                update_post_meta($post_id, 'property_suburb_name_' . $index, $sname);
                update_post_meta($post_id, 'property_suburb_region_' . $index, $sregion);
                update_post_meta($post_id, 'property_suburb_type_' . $index, $stype);

                if ($index === 0) {
                    $primary_suburb = $sname;
                    $primary_region = $sregion ?: 'Auckland';
                }
            }
        }
        update_post_meta($post_id, 'ipp_suburb', $primary_suburb);
        update_post_meta($post_id, 'information_suburb', $primary_suburb); // legacy
        update_post_meta($post_id, 'ipp_region', $primary_region);
        update_post_meta($post_id, 'information_region', $primary_region); // legacy

        // === Custom Fields ===
        $custom_list = self::arr_get($property, 'PropertyCustomList', []);
        if (!empty($custom_list) && is_array($custom_list)) {
            $stored_customs = [];
            foreach ($custom_list as $custom_field) {
                if (!is_array($custom_field)) continue;
                $name = isset($custom_field['PropertyCustomName'])
                    ? $custom_field['PropertyCustomName']
                    : (isset($custom_field['CustomFieldName']) ? $custom_field['CustomFieldName'] : '');
                $value = isset($custom_field['PropertyCustomValue'])
                    ? $custom_field['PropertyCustomValue']
                    : (isset($custom_field['CustomFieldValue']) ? $custom_field['CustomFieldValue'] : '');
                if ($name) {
                    $key = 'ipp_custom_' . sanitize_key($name);
                    update_post_meta($post_id, $key, sanitize_text_field($value));
                    $stored_customs[$key] = $value;
                }
            }
            update_post_meta($post_id, 'ipp_custom_fields', wp_json_encode($stored_customs));
        }

        // === User Commissions (store as JSON) ===
        $commissions = self::arr_get($property, 'PropertyUserCommissions', []);
        if (!empty($commissions) && is_array($commissions)) {
            update_post_meta($post_id, 'ipp_user_commissions', wp_json_encode($commissions));
        }

        // === Store raw JSON for future use ===
        update_post_meta($post_id, 'ipp_raw_data', wp_json_encode($property));

        // === Set taxonomy terms based on property data ===
        $property_class = sanitize_text_field(self::arr_get($features, 'PropertyClass'));
        if ($property_class && taxonomy_exists('palace-property-type')) {
            wp_set_object_terms($post_id, $property_class, 'palace-property-type');
        }

        $property_status = sanitize_text_field(self::arr_get($property, 'PropertyStatus'));
        if ($property_status && taxonomy_exists('palace-property-status')) {
            wp_set_object_terms($post_id, $property_status, 'palace-property-status');
        }

        if ($primary_region && taxonomy_exists('palace-property-region')) {
            wp_set_object_terms($post_id, $primary_region, 'palace-property-region');
        }

        $mgmt_type = sanitize_text_field(self::arr_get($property, 'PropertyManagementType'));
        if ($mgmt_type && taxonomy_exists('palace-property-management')) {
            wp_set_object_terms($post_id, $mgmt_type, 'palace-property-management');
        }

        // === Schedule gallery fetch ===
        // Clear ALL existing gallery cron events for this property first
        $crons = _get_cron_array();
        if ( is_array( $crons ) ) {
            foreach ( $crons as $ts => $hooks ) {
                if ( isset( $hooks['update_integrate_palace_gallery'] ) ) {
                    foreach ( $hooks['update_integrate_palace_gallery'] as $hash => $event ) {
                        $args = $event['args'] ?? array();
                        if ( isset( $args[0] ) && (int) $args[0] === (int) $post_id ) {
                            wp_unschedule_event( $ts, 'update_integrate_palace_gallery', $args );
                        }
                    }
                }
            }
        }
        // Reset retry counter and schedule fresh
        delete_post_meta( $post_id, 'ipp_gallery_sync_retries' );
        wp_schedule_single_event( time() + 10, 'update_integrate_palace_gallery', array( $post_id, $property_code ) );
        IntegratePalace_Properties_Admin::update_gallery_sync_status( $post_id, 'queued', 'Queued for gallery sync.' );
        update_post_meta( $post_id, 'ipp_gallery_sync_started_at', current_time( 'mysql' ) );

        /** @hook ipp_after_property_save — Fires after a property is saved/updated via webhook (all meta written). */
        do_action( 'ipp_after_property_save', $post_id, $property );

        do_action('ipp_property_synced', $post_id, $property);

        // Update last sync time — tracks when properties were last received via webhook
        update_option( 'ipp_last_sync_time', current_time( 'mysql' ), false );
        $sync_count = wp_count_posts( 'palace-properties' );
        update_option( 'ipp_last_sync_count', isset( $sync_count->publish ) ? $sync_count->publish : 0, false );

        return new WP_REST_Response(array('status' => 'success'), 200);
    }
}
