<?php

namespace Blazemedia\Affiliation\Providers;

use Blazemedia\Affiliation\Rendering\Disclaimer;
use Blazemedia\Affiliation\Rendering\RenderResponse;
use Blazemedia\Affiliation\Rendering\Parameters;
use Blazemedia\Affiliation\Utils\Logger;

class RenderHookServiceProvider implements Contract\ServiceProviderInterface
{
    use Trait\HasFormatsInjector, Trait\HasServerRequest, Trait\HandleZoneFormat, Trait\LinkConverter, Trait\HasPostMetaManager;

    protected \WP_Post $post;
    protected RenderResponse $renderResponse;
    private Disclaimer $disclaimer;
	private static array $preparedPosts = [];

    public function __construct()
    {
        $this->disclaimer = Disclaimer::getInstance();
        add_filter('blz_affiliation_render_content', [ $this, 'renderContentWithAffiliation' ], 10, 2);
    }

    public function register(): void
    {
        // No runtime registration needed; the public filter is global
    }

    /**
     * Hook handler: renders formats into the provided content and returns the processed output.
     * Can be called via: apply_filters('blz_affiliation_render_content', $content, $post);
     *
     * @param string             $content
     * @param null|int|\WP_Post $post Optional post or post ID to target. Defaults to current post.
     * @return string
     */
    public function renderContentWithAffiliation(string $content, $post = null): string
    {
        $resolvedPost = null;
        if ($post instanceof \WP_Post) {
            $resolvedPost = $post;
        } elseif (!is_null($post)) {
            $resolvedPost = get_post((int) $post);
        } else {
            $resolvedPost = function_exists('get_post') ? get_post() : null;
        }

        if (!$resolvedPost instanceof \WP_Post) {
            return $content;
        }

        // Seed post content from the provided content
        $resolvedPost->post_content = $content;
        $this->post = $resolvedPost;

        // Inline prepare: old shortcodes, zone handling, then one abstract extension action
        $working = clone $resolvedPost;
        $working = $this->handleOldShortcode($working);
        $working = $this->handleZoneRendering($working);

        // Compute render response using prepared post
        $this->renderResponse = $this->getRenderResponseForPost($working);

        // Inject formats into prepared content, without bm_post/disclaimer in this path
        $preparedContent = (string) $working->post_content;
        $content = $this->inject(content: $preparedContent, renderResponse: $this->renderResponse, bmPostMarkup: false, disclaimer: false);
        return $content;
    }

	protected function getRenderResponseForPost(\WP_Post $post): RenderResponse
    {
        // Compare signature against stored child signature to decide whether to reuse cache
        $currentSignature = (new Parameters($post))->getSignature();
        $storedSignature = $this->getMetaSignature($post, true);

        if ($currentSignature === $storedSignature) {
            $renderResponse = $this->getMetaRenderResponse($post, true);
            if (!$renderResponse->isEmpty()) {
                return $renderResponse;
            }
        } else {
            $this->deleteMetaRenderResponse($post);
        }

        // Fetch from server on cache miss
        $renderResponse = $this->requestFormats($post, true);
        if ($renderResponse->isEmpty()) {
            Logger::write('RenderHookServiceProvider: Remote render response is empty, returning original content', 'ERROR');
        } else {
            $this->setMetaRenderResponse($post, $renderResponse, true);
        }

        return $renderResponse;
    }
}


