<?php
declare(strict_types=1);

namespace Ekesto\CacheInvalidator\Integrations\Caching;

use Ekesto\CacheInvalidator\Core\EmissionHelper;
use Ekesto\CacheInvalidator\Support\Debug;

/**
 * Shared mechanics for single-target cache adapter invalidation signals.
 */
trait EmitsSingleTargetCacheAdapterInvalidation
{
    /**
     * Returns the adapter source key used in signal logs.
     *
     * @return string
     */
    abstract protected function getSingleTargetSignalSource(): string;

    /**
     * Enforce one URL, guard the signal, log, and emit the invalidation.
     *
     * @param string              $hook Hook name.
     * @param array<int,string>   $targetUrls Single target URL list.
     * @param array<string,mixed> $validated Validated adapter payload.
     * @param array<string,mixed> $logContext Shared log context.
     * @param array<string,mixed> $emissionContext Emission context.
     * @return bool True when emitted.
     */
    private function emitSingleTargetInvalidation(
        string $hook,
        array $targetUrls,
        array $validated,
        array $logContext,
        array $emissionContext
    ): bool {
        $source = $this->getSingleTargetSignalSource();

        if (count($targetUrls) !== 1) {
            $this->logIgnoredSingleTarget($hook, 'invalid_url_count', array_merge($logContext, [
                'post_id' => isset($validated['post_id']) ? (int) $validated['post_id'] : 0,
                'url_count' => count($targetUrls),
            ]));
            return false;
        }

        // Guard dedupe identity depends on (adapter + hook + signal_type + url hash).
        // Do not alter $targetUrls shape or ordering before this call.
        if (!AdapterSignalGuard::shouldProcessSignal($source, $hook, 'targeted', $targetUrls)) {
            $this->logIgnoredSingleTarget($hook, 'guard_rejected', array_merge($logContext, [
                'url' => isset($validated['url']) ? (string) $validated['url'] : '',
                'post_id' => isset($validated['post_id']) ? (int) $validated['post_id'] : 0,
            ]));
            return false;
        }

        Debug::log('cache_plugin_single_target_detected', array_merge([
            'source' => $source,
            'hook' => $hook,
            'accepted' => true,
        ], $logContext, [
            'mode' => isset($validated['mode']) ? (string) $validated['mode'] : '',
            'url' => isset($validated['url']) ? (string) $validated['url'] : '',
            'post_id' => isset($validated['post_id']) ? (int) $validated['post_id'] : 0,
            'trusted' => true,
        ]));

        EmissionHelper::emit($targetUrls, $emissionContext);

        return true;
    }

    /**
     * Log an ignored manual single-target signal.
     *
     * @param string              $hook Hook name.
     * @param string              $reason Ignore reason key.
     * @param array<string,mixed> $context Additional context.
     * @return void
     */
    private function logIgnoredSingleTarget(string $hook, string $reason, array $context = []): void
    {
        if (Debug::verboseEnabled()) {
            Debug::log('cache_plugin_single_target_ignored', array_merge([
                'source' => $this->getSingleTargetSignalSource(),
                'hook' => $hook,
                'accepted' => false,
                'reason' => $reason,
                'url' => '',
                'post_id' => 0,
            ], $context));
        }
    }
}
