<?php

declare(strict_types=1);

namespace ImovelZapAi\Owners\Application\Actions;

use App\Models\User;
use Illuminate\Support\Facades\DB;
use ImovelZapAi\Owners\Application\Services\ListingHistoryWriter;
use ImovelZapAi\Owners\Domain\Enums\ListingHistoryEvent;
use ImovelZapAi\Owners\Domain\Exceptions\OwnerException;
use ImovelZapAi\Owners\Infrastructure\Persistence\Eloquent\ListingOpportunityModel;

final class UpdateListingEvaluationAction
{
    public function __construct(
        private readonly ListingHistoryWriter $history,
    ) {}

    /**
     * @param  array{
     *     owner_asking_price?: float|string|null,
     *     agency_recommended_price?: float|string|null,
     *     listed_price?: float|string|null,
     *     conservation_state?: string|null,
     *     pending_documents?: string|null,
     *     sale_potential?: string|null,
     *     evaluation_notes?: string|null,
     * }  $data
     */
    public function execute(ListingOpportunityModel $opportunity, User $actor, array $data): ListingOpportunityModel
    {
        if ($opportunity->isClosed()) {
            throw OwnerException::invalidState('oportunidade encerrada.');
        }

        return DB::transaction(function () use ($opportunity, $actor, $data): ListingOpportunityModel {
            $before = $opportunity->only([
                'owner_asking_price', 'agency_recommended_price', 'listed_price',
                'conservation_state', 'pending_documents', 'sale_potential', 'evaluation_notes',
            ]);

            $opportunity->forceFill(array_merge($data, ['last_activity_at' => now()]))->save();

            $this->history->write(
                $opportunity->tenant_id,
                ListingHistoryEvent::EvaluationUpdated,
                opportunityId: $opportunity->id,
                ownerId: $opportunity->owner_id,
                actorUserId: (int) $actor->id,
                before: $before,
                after: $opportunity->only(array_keys($before)),
                message: 'Avaliação atualizada.',
            );

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