<?php

declare(strict_types=1);

namespace ImovelZapAi\Publishing\Application\Actions;

use App\Models\User;
use Illuminate\Support\Facades\DB;
use ImovelZapAi\Properties\Infrastructure\Persistence\Eloquent\PropertyModel;
use ImovelZapAi\Publishing\Application\Services\PublicationLogRecorder;
use ImovelZapAi\Publishing\Application\Services\PublicationStatusAggregator;
use ImovelZapAi\Publishing\Domain\Enums\PublicationLogEvent;
use ImovelZapAi\Publishing\Domain\Enums\PublicationTargetStatus;
use ImovelZapAi\Publishing\Infrastructure\Jobs\ProcessPropertyPublicationJob;
use ImovelZapAi\Publishing\Infrastructure\Persistence\Eloquent\PublicationTargetModel;
use ImovelZapAi\Publishing\Infrastructure\Persistence\Eloquent\PublisherModel;

/**
 * Enfileira publicação/sincronização — nunca chama o portal diretamente.
 */
final class QueuePropertyPublicationAction
{
    public function __construct(
        private readonly EnsurePropertyPublicationAction $ensurePublication,
        private readonly PublicationLogRecorder $logRecorder,
        private readonly PublicationStatusAggregator $statusAggregator,
    ) {}

    public function execute(
        PropertyModel $property,
        PublisherModel $publisher,
        ?User $actor = null,
        bool $isUpdate = false,
    ): PublicationTargetModel {
        $target = DB::transaction(function () use ($property, $publisher, $actor, $isUpdate): PublicationTargetModel {
            $publication = $this->ensurePublication->execute($property, $actor);

            /** @var PublicationTargetModel $target */
            $target = PublicationTargetModel::query()->updateOrCreate(
                [
                    'publication_id' => $publication->id,
                    'publisher_id' => $publisher->id,
                ],
                [
                    'tenant_id' => $property->tenant_id,
                ],
            );

            if ($target->status === PublicationTargetStatus::Publishing) {
                return $target;
            }

            $target->update([
                'status' => PublicationTargetStatus::Publishing,
                'last_error' => null,
            ]);

            $this->logRecorder->record(
                target: $target->fresh(),
                event: PublicationLogEvent::Queued,
                message: $isUpdate ? 'Sincronização enfileirada.' : 'Publicação enfileirada.',
                triggeredBy: $actor?->id,
            );

            $this->statusAggregator->refresh($publication->fresh(['targets']));

            return $target->fresh();
        });

        ProcessPropertyPublicationJob::dispatch(
            tenantId: (string) $property->tenant_id,
            propertyId: (string) $property->id,
            publisherId: (string) $publisher->id,
            isUpdate: $isUpdate,
            actorId: $actor?->id,
        );

        return $target;
    }
}
