<?php

declare(strict_types=1);

namespace ImovelZapAi\Visits\Application\Actions;

use App\Models\User;
use Illuminate\Support\Facades\DB;
use ImovelZapAi\Visits\Application\Services\VisitLogWriter;
use ImovelZapAi\Visits\Application\Services\VisitSnapshotter;
use ImovelZapAi\Visits\Domain\Enums\VisitLogEvent;
use ImovelZapAi\Visits\Domain\Enums\VisitStatus;
use ImovelZapAi\Visits\Domain\Exceptions\VisitException;
use ImovelZapAi\Visits\Infrastructure\Persistence\Eloquent\VisitModel;

final class CheckInVisitAction
{
    public function __construct(
        private readonly VisitLogWriter $logWriter,
        private readonly VisitSnapshotter $snapshotter,
    ) {}

    public function execute(
        VisitModel $visit,
        User $actor,
        ?float $latitude = null,
        ?float $longitude = null,
        ?string $notes = null,
    ): VisitModel {
        if (! $visit->status->canCheckIn()) {
            throw VisitException::invalidState($visit->status->value, 'check_in');
        }

        return DB::transaction(function () use ($visit, $actor, $latitude, $longitude, $notes): VisitModel {
            $before = $this->snapshotter->snapshot($visit);

            $visit->forceFill([
                'status' => VisitStatus::InProgress,
                'check_in_at' => now(),
                'check_in_latitude' => $latitude,
                'check_in_longitude' => $longitude,
                'check_in_notes' => $notes,
            ])->save();

            $this->logWriter->write(
                $visit->tenant_id,
                $visit->id,
                VisitLogEvent::CheckedIn,
                actorUserId: (int) $actor->id,
                before: $before,
                after: $this->snapshotter->snapshot($visit->fresh()),
                message: 'Check-in registrado.',
            );

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