<?php

namespace App\Modules\Procurement\Services;

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

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

    private function enabled(): bool
    {
        return (bool) config('procurement.observability.enabled', true);
    }

    /** @param  array<string, mixed>  $context */
    public function postingFailure(string $reason, array $context = []): void
    {
        if ($this->enabled()) {
            Log::warning('procurement.receiving.posting_failure '.$reason, $context);
        }
        $this->persistProcurement('receipt_posting_failure', 'error', $reason, 'Posting failure: '.$reason, $context);
    }

    /** @param  array<string, mixed>  $context */
    public function duplicatePostingAttempt(array $context = []): void
    {
        if ($this->enabled()) {
            Log::notice('procurement.receiving.duplicate_posting_attempt', $context);
        }
        $this->persistProcurement(
            'duplicate_posting_attempt',
            'warning',
            'duplicate_posting_attempt',
            'Duplicate posting attempt (idempotent replay).',
            $context,
        );
    }

    public function quarantineExcluded(int $lineId, int $receiptId): void
    {
        if ($this->enabled()) {
            Log::notice('procurement.receiving.quarantine_excluded', [
                'goods_receipt_item_id' => $lineId,
                'goods_receipt_id' => $receiptId,
            ]);
        }
        $tenantId = (int) (\App\Modules\Procurement\Models\GoodsReceipt::withoutGlobalScopes()->whereKey($receiptId)->value('tenant_id') ?? 0);
        $this->recorder->record(
            $tenantId,
            'procurement',
            'quarantine_blocked_receive',
            'warning',
            'quarantine_excluded',
            'Quarantined line excluded from receive validation.',
            null,
            'goods_receipt_item',
            $lineId,
            ['goods_receipt_id' => $receiptId],
        );
    }

    /** @param  array<string, mixed>  $context */
    public function overReceiveAttempt(array $context = []): void
    {
        if ($this->enabled()) {
            Log::warning('procurement.receiving.over_receive_attempt', $context);
        }
        $this->persistProcurement(
            'over_receive_attempt',
            'warning',
            'over_receive_attempt',
            'Over-receive attempt blocked.',
            $context,
        );
    }

    /** @param  array<string, mixed>  $context */
    private function persistProcurement(
        string $category,
        string $severity,
        string $eventCode,
        string $summary,
        array $context,
    ): void {
        $tenantId = (int) ($context['tenant_id'] ?? 0);
        if ($tenantId <= 0) {
            return;
        }
        $refId = isset($context['goods_receipt_id']) ? (int) $context['goods_receipt_id'] : null;

        $this->recorder->record(
            $tenantId,
            'procurement',
            $category,
            $severity,
            $eventCode,
            $summary,
            isset($context['correlation_id']) ? (string) $context['correlation_id'] : null,
            $refId !== null ? 'goods_receipt' : null,
            $refId,
            $context,
        );
    }
}
