<?php

namespace App\Modules\Sales\Services;

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

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

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

    /** @param  array<string, mixed>  $meta */
    public function allocationFailure(string $code, string $message, array $meta): void
    {
        $this->log('warning', 'sales.allocation_failure', $code, $meta);
        $this->persist('sales_outbound', 'allocation_failure', 'warning', $code, $message, $meta);
    }

    /** @param  array<string, mixed>  $meta */
    public function overAllocationAttempt(array $meta): void
    {
        $this->log('warning', 'sales.over_allocation_attempt', 'over_allocation', $meta);
        $this->persist('sales_outbound', 'allocation_guard', 'warning', 'over_allocation_attempt', 'Over-allocation blocked.', $meta);
    }

    /** @param  array<string, mixed>  $meta */
    public function duplicateAllocationReplay(array $meta): void
    {
        $this->log('notice', 'sales.duplicate_allocation', 'duplicate_allocation', $meta);
        $this->persist('sales_outbound', 'allocation_idempotency', 'info', 'duplicate_allocation_replay', 'Idempotent allocation replay.', $meta);
    }

    /** @param  array<string, mixed>  $meta */
    public function fulfillmentFailure(string $code, string $message, array $meta): void
    {
        $this->log('error', 'sales.fulfillment_failure', $code, $meta);
        $this->persist('sales_outbound', 'fulfillment_failure', 'error', $code, $message, $meta);
    }

    /** @param  array<string, mixed>  $meta */
    public function duplicateFulfillmentAttempt(array $meta): void
    {
        $this->log('notice', 'sales.duplicate_fulfillment', 'duplicate_fulfillment', $meta);
        $this->persist('sales_outbound', 'fulfillment_idempotency', 'warning', 'duplicate_fulfillment_attempt', 'Duplicate fulfillment replay.', $meta);
    }

    /** @param  array<string, mixed>  $meta */
    public function reservationLeakageSignal(array $meta): void
    {
        $this->log('warning', 'sales.reservation_leakage', 'reservation_drift', $meta);
        $this->persist('sales_outbound', 'reservation_integrity', 'warning', 'reservation_leakage_signal', 'Sales line vs ledger reservation mismatch.', $meta);
    }

    /** @param  array<string, mixed>  $meta */
    private function log(string $level, string $channel, string $code, array $meta): void
    {
        if (! $this->enabled()) {
            return;
        }
        Log::log($level, $channel.' '.$code, $meta);
    }

    /** @param  array<string, mixed>  $meta */
    private function persist(
        string $channel,
        string $category,
        string $severity,
        string $eventCode,
        string $summary,
        array $meta,
    ): void {
        if (! $this->enabled()) {
            return;
        }
        $tenantId = (int) ($meta['tenant_id'] ?? 0);
        if ($tenantId <= 0) {
            return;
        }
        $this->recorder->record(
            $tenantId,
            $channel,
            $category,
            $severity,
            $eventCode,
            $summary,
            isset($meta['correlation_id']) ? (string) $meta['correlation_id'] : null,
            isset($meta['reference_type']) ? (string) $meta['reference_type'] : null,
            isset($meta['reference_id']) ? (int) $meta['reference_id'] : null,
            $meta,
        );
    }
}
