<?php

namespace App\Modules\Inventory\Stock\Services;

use App\Modules\Operations\Services\OperationalSignalRecorder;
use Illuminate\Support\Facades\Log;

final class InventoryStockObservability
{
    public function __construct(
        private readonly OperationalSignalRecorder $recorder,
    ) {}

    /** @param  array<string, mixed>  $context */
    public function invariantViolation(string $message, array $context = []): void
    {
        if (! config('inventory.observability.enabled', true)) {
            return;
        }
        Log::warning('inventory.stock.invariant_violation '.$message, $context);
        $this->persistInventory('inventory_invariant', 'error', $message, 'Invariant: '.$message, $context);
    }

    /** @param  array<string, mixed>  $context */
    public function deadlockRetry(int $attempt, array $context = []): void
    {
        if (! config('inventory.observability.enabled', true)) {
            return;
        }
        Log::notice('inventory.stock.deadlock_retry', array_merge(['attempt' => $attempt], $context));
    }

    /** @param  array<string, mixed>  $context */
    public function rebuildMismatch(string $message, array $context = []): void
    {
        if (! config('inventory.observability.enabled', true)) {
            return;
        }
        Log::warning('inventory.stock.rebuild_mismatch '.$message, $context);
        $this->persistInventory('rebuild_mismatch', 'error', $message, 'Rebuild mismatch: '.$message, $context);
    }

    /** @param  array<string, mixed>  $context */
    public function duplicateReplay(string $idempotencyKey, array $context = []): void
    {
        if (! config('inventory.observability.enabled', true)) {
            return;
        }
        Log::info('inventory.stock.duplicate_replay', array_merge(['key' => $idempotencyKey], $context));
        $ctx = array_merge($context, ['idempotency_key' => $idempotencyKey]);
        $this->persistInventory('duplicate_stock_replay', 'info', 'duplicate_replay', 'Duplicate stock movement replay.', $ctx);
    }

    /** @param  array<string, mixed>  $context */
    private function persistInventory(
        string $category,
        string $severity,
        string $eventCode,
        string $summary,
        array $context,
    ): void {
        $tenantId = (int) ($context['tenant_id'] ?? 0);
        if ($tenantId <= 0) {
            return;
        }
        $this->recorder->record(
            $tenantId,
            'inventory',
            $category,
            $severity,
            $eventCode,
            $summary,
            $context['correlation_id'] ?? null,
            isset($context['projection_id']) ? 'inventory_stock_projection' : null,
            isset($context['projection_id']) ? (int) $context['projection_id'] : null,
            $context,
        );
    }
}
