<?php

declare(strict_types=1);

namespace ImovelZapAi\Financial\Application\Actions;

use App\Models\User;
use Illuminate\Support\Facades\DB;
use ImovelZapAi\Financial\Domain\Enums\TransactionStatus;
use ImovelZapAi\Financial\Domain\Enums\TransactionType;
use ImovelZapAi\Financial\Domain\Events\TransactionCreated;
use ImovelZapAi\Financial\Domain\Exceptions\FinancialException;
use ImovelZapAi\Financial\Infrastructure\Persistence\Eloquent\FinancialTransactionModel;
use ImovelZapAi\Sales\Infrastructure\Persistence\Eloquent\DealModel;

final class CreateFinancialTransactionAction
{
    /**
     * @param  array{
     *     deal_id: string,
     *     type: string,
     *     amount: float|string,
     *     status?: string|null,
     *     currency?: string|null,
     *     due_at?: string|null,
     *     description?: string|null,
     *     signature_request_id?: string|null,
     *     business_document_id?: string|null,
     *     meta?: array|null,
     * }  $data
     */
    public function execute(string $tenantId, ?User $actor, array $data): FinancialTransactionModel
    {
        return DB::transaction(function () use ($tenantId, $actor, $data): FinancialTransactionModel {
            $deal = DealModel::query()
                ->where('tenant_id', $tenantId)
                ->find($data['deal_id']);

            if ($deal === null) {
                throw FinancialException::notFound('Oportunidade');
            }

            $type = TransactionType::tryFrom((string) $data['type']) ?? TransactionType::Other;
            $status = TransactionStatus::tryFrom((string) ($data['status'] ?? TransactionStatus::Pending->value))
                ?? TransactionStatus::Pending;

            $transaction = FinancialTransactionModel::query()->create([
                'tenant_id' => $tenantId,
                'deal_id' => $deal->id,
                'signature_request_id' => $data['signature_request_id'] ?? null,
                'business_document_id' => $data['business_document_id'] ?? null,
                'type' => $type,
                'status' => $status,
                'amount' => $data['amount'],
                'currency' => $data['currency'] ?? 'BRL',
                'due_at' => $data['due_at'] ?? null,
                'description' => $data['description'] ?? $type->label(),
                'meta' => $data['meta'] ?? null,
                'created_by' => $actor?->id,
            ]);

            TransactionCreated::dispatch($tenantId, (string) $transaction->id);

            return $transaction;
        });
    }
}
