<?php

namespace Blazemedia\Affiliation\Providers;

use Blazemedia\Affiliation\Rendering\RenderResponse;
use Blazemedia\Affiliation\Rendering\Parameters;
use Blazemedia\Affiliation\Support\Environment;
use Blazemedia\Affiliation\Utils\Logger;

class SyncProcessingServiceProvider implements Contract\ServiceProviderInterface {

    use Trait\HasServerRequest, Trait\HandleZoneFormat, Trait\LinkConverter, Trait\HasPostMetaManager;

    public function __construct() {

        // Esegue in modo sincrono l'elaborazione quando lo stato cambia da bozza a qualsiasi altro
        add_action('transition_post_status', [ $this, 'processTransition' ], 10, 3);

        // Mostra una notifica in admin basata sul transient di errore, se presente
        add_action('admin_notices', [ $this, 'showErrorNotice' ]);
    }

    public function register(): void {}

    /**
     * Esegue la logica di conversione/linking/formati al cambio di stato.
     */
    public function processTransition( string $new_status, string $old_status, \WP_Post $post ): void {

        if (! in_array($post->post_type, Environment::get('BLAZE_AFFILIATION_POST_TYPES')) ) return;

        // Centralized preparation via action/filter
        do_action('blz_affiliation_prepare_post', $post);
        $prepared = apply_filters('blz_affiliation_get_prepared_post', null, $post);
        if ($prepared instanceof \WP_Post) {
            $post = $prepared;
        }

        // Sincrono: se si passa da bozza/auto-draft a un altro stato (publish, future, pending, private, ecc.)
        if ( in_array($old_status, ['draft','auto-draft'], true) && $new_status !== $old_status ) {
            $this->saveAffiliationMeta($post);
            return;
        }

        // Aggiornamento di un post già pubblicato: riesegui la logica
        if ($old_status === 'publish' && $new_status === 'publish') {
            $this->saveAffiliationMeta($post);
            return;
        }
    }

    protected function saveAffiliationMeta( \WP_Post $post ) : void {
        try {
            // Use signature compare to avoid unnecessary calls
            $currentSignature = (new Parameters($post))->getSignature();
            $storedSignature  = $this->getMetaSignature($post);

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

            /** @var RenderResponse $renderResponse */
            $renderResponse = $this->requestFormats( $post );

            if ($renderResponse->isEmpty()) {
                throw new \Exception("Nessun formato ricevuto per post {$post->ID}");
            }

            // Persist meta for future cache hits
            $this->setMetaRenderResponse($post, $renderResponse);

        } catch (\Exception $e) {
            Logger::write("Errore in saveAffiliationClient per post {$post->ID}: " . $e->getMessage());

            // Admin notice tramite transient
            $transient_name = "spw_error_notice_{$post->ID}";
            set_transient($transient_name, $e->getMessage(), 3600);
        }
    }

    public function showErrorNotice(): void {
        global $pagenow, $post;

        if ( $pagenow === 'post.php' && isset($post) && $post instanceof \WP_Post ) {
            $transient_name = "spw_error_notice_{$post->ID}";
            if ( $msg = get_transient($transient_name) ) {
                echo '<div class="notice notice-error is-dismissible">';
                echo '<p><strong>Attenzione:</strong> la chiamata a Affiliation per questo post è fallita: <em>' . esc_html($msg) . '</em></p>';
                echo '</div>';
                delete_transient($transient_name);
            }
        }
    }
}
