<?php
/**
 * Tool: swap_image_in_block
 *
 * Replace the image inside a specific image-bearing block. Works on
 * core/image, core/cover, uagb/image, generateblocks/image. The user
 * normally points at the image via the rail's pick mode (which captures
 * its src), so the locator is `{ type: 'image_src', value: <full or
 * partial src> }`. Description-based locators ('text' near the image)
 * also work.
 *
 * The new image must already live in the WordPress media library. The
 * rail's media picker (or the upload bubble) returns a URL the cloud
 * passes here as `new_image_url`.
 */
if (!defined('ABSPATH')) exit;

function swcp_tool_swap_image_in_block($input, $ctx) {
    $page_arg  = isset($input['page']) ? $input['page'] : 'current';
    $locator   = isset($input['locator']) && is_array($input['locator']) ? $input['locator'] : null;
    $new_url   = isset($input['new_image_url']) ? trim((string) $input['new_image_url']) : '';
    $new_alt   = isset($input['new_alt']) ? sanitize_text_field((string) $input['new_alt']) : null;

    if (!$new_url || !preg_match('#^https?://#i', $new_url)) {
        return ['ok' => false, 'message' => 'I need a full image URL from the WordPress media library to swap in.'];
    }
    if (!$locator) {
        return ['ok' => false, 'message' => 'I need to know which image to replace. Click the image in the page or describe it.'];
    }

    $resolved = swcp_resolve_or_error($page_arg, $ctx['post_id'] ?? 0);
    if (is_array($resolved) && isset($resolved['ok']) && !$resolved['ok']) return $resolved;
    $post = $resolved;

    $before_html = (string) $post->post_content;
    $blocks      = swcp_get_blocks($post);

    $found = swcp_find_block_by_locator($blocks, $locator);
    if (!$found) {
        return swcp_locator_ambiguous_or_missing($blocks, $locator) + ['page_id' => (int) $post->ID];
    }

    $old_src = swcp_locator_image_src($found['block']);

    $ok = swcp_mutate_at_path($blocks, $found['path'], function ($block) use ($new_url, $new_alt, $old_src) {
        $name  = isset($block['blockName']) ? (string) $block['blockName'] : '';
        if (!isset($block['attrs']) || !is_array($block['attrs'])) $block['attrs'] = [];

        // Update attrs first.
        if ($name === 'core/image' || in_array($name, ['uagb/image', 'generateblocks/image'], true)) {
            $block['attrs']['url'] = $new_url;
            $block['attrs']['id']  = null; // attachment id is no longer accurate; let WP refetch
            if ($new_alt !== null) $block['attrs']['alt'] = $new_alt;
        }
        if ($name === 'core/cover') {
            $block['attrs']['url'] = $new_url;
            $block['attrs']['id']  = null;
        }

        // Patch innerHTML / innerContent: replace old src in <img src> and
        // background-image:url(...) so the rendered HTML matches the new
        // attrs without waiting for a re-render.
        $patch = function ($html) use ($new_url, $new_alt, $old_src) {
            if (!is_string($html) || $html === '') return $html;
            if ($old_src && strpos($html, $old_src) !== false) {
                $html = str_replace($old_src, $new_url, $html);
            } else {
                // No known old src — try a generic <img src=""> swap.
                $html = preg_replace('#(<img\b[^>]*\bsrc=")[^"]*(")#i', '$1' . esc_url($new_url) . '$2', $html, 1);
            }
            if ($new_alt !== null) {
                $alt_attr = ' alt="' . esc_attr($new_alt) . '"';
                if (preg_match('#<img\b[^>]*\balt="[^"]*"#i', $html)) {
                    $html = preg_replace('#(<img\b[^>]*\b)alt="[^"]*"#i', '$1alt="' . esc_attr($new_alt) . '"', $html, 1);
                } elseif (preg_match('#<img\b[^>]*>#i', $html)) {
                    $html = preg_replace('#(<img\b[^>]*?)(\s*/?>)#i', '$1' . $alt_attr . '$2', $html, 1);
                }
            }
            return $html;
        };
        if (isset($block['innerHTML'])) {
            $block['innerHTML'] = $patch((string) $block['innerHTML']);
        }
        if (isset($block['innerContent']) && is_array($block['innerContent'])) {
            foreach ($block['innerContent'] as &$ic) {
                if (is_string($ic)) $ic = $patch($ic);
            }
            unset($ic);
        }
        return $block;
    });

    if (!$ok) {
        return ['ok' => false, 'message' => 'Found the image but failed to apply the swap.'];
    }

    $saved = swcp_save_blocks($post->ID, $blocks);
    if (!$saved) {
        return ['ok' => false, 'message' => 'Found the image but failed to save the page.'];
    }

    return [
        'ok'               => true,
        'page_id'          => (int) $post->ID,
        'message'          => 'Swapped the image on "' . esc_html(get_the_title($post)) . '".',
        'view_url'         => swcp_view_url_for($post->ID),
        'edit_url'         => swcp_edit_url_for($post->ID),
        'old_src'          => $old_src,
        'new_src'          => $new_url,
        'requires_refresh' => true,
        'undo' => [
            'tool'  => 'restore_page_version',
            'input' => ['post_id' => (int) $post->ID, 'snapshot_html' => $before_html],
            'label' => 'Undo',
        ],
    ];
}
