<?php

declare(strict_types=1);

namespace App\Business\DataImport;

use App\Business\DataImport\Enums\DataImportBatchStatus;
use App\Models\DberpDataImportBatch;
use App\Services\DberpAuditService;
use App\Support\DberpAuditCorrelationContext;

final class DataImportAuditLogger
{
    public function __construct(
        private readonly DberpAuditService $auditService,
    ) {}

    public function logPrechecked(DberpDataImportBatch $batch): void
    {
        $this->withBatchCorrelation($batch, function () use ($batch): void {
            $this->auditService->log(
                'dberp.data_import.batch_prechecked',
                $batch,
                null,
                $this->batchSnapshot($batch),
            );
        });
    }

    public function logStarted(DberpDataImportBatch $batch): void
    {
        $this->withBatchCorrelation($batch, function () use ($batch): void {
            $this->auditService->log(
                'dberp.data_import.batch_started',
                $batch,
                null,
                $this->batchSnapshot($batch),
            );
        });
    }

    public function logCompleted(DberpDataImportBatch $batch): void
    {
        $this->withBatchCorrelation($batch, function () use ($batch): void {
            $this->auditService->log(
                'dberp.data_import.batch_completed',
                $batch,
                null,
                $this->batchSnapshot($batch),
            );
        });
    }

    public function logFailed(DberpDataImportBatch $batch, ?string $reason = null): void
    {
        $this->withBatchCorrelation($batch, function () use ($batch, $reason): void {
            $snapshot = $this->batchSnapshot($batch);

            if ($reason !== null && $reason !== '') {
                $snapshot['failure_reason'] = $reason;
            }

            $this->auditService->log(
                'dberp.data_import.batch_failed',
                $batch,
                null,
                $snapshot,
            );
        });
    }

    public function logDeleted(DberpDataImportBatch $batch): void
    {
        $this->withBatchCorrelation($batch, function () use ($batch): void {
            $this->auditService->log(
                'dberp.data_import.batch_deleted',
                $batch,
                $this->batchSnapshot($batch),
                null,
            );
        });
    }

    /**
     * @return array<string, mixed>
     */
    private function batchSnapshot(DberpDataImportBatch $batch): array
    {
        return [
            'batch_no' => $batch->batch_no,
            'import_type' => $batch->import_type->value,
            'status' => $batch->status instanceof DataImportBatchStatus ? $batch->status->value : (string) $batch->status,
            'source_filename' => $batch->source_filename,
            'total_rows' => (int) $batch->total_rows,
            'success_rows' => (int) $batch->success_rows,
            'failed_rows' => (int) $batch->failed_rows,
            'correlation_id' => $batch->correlation_id,
        ];
    }

    private function withBatchCorrelation(DberpDataImportBatch $batch, callable $callback): void
    {
        $previousCorrelationId = DberpAuditCorrelationContext::id();

        if ($batch->correlation_id !== null && $batch->correlation_id !== '') {
            DberpAuditCorrelationContext::reset($batch->correlation_id);
        }

        try {
            $callback();
        } finally {
            DberpAuditCorrelationContext::reset($previousCorrelationId);
        }
    }
}
