<?php

declare(strict_types=1);

namespace ImovelZapAi\Signatures\Infrastructure\Providers\Drivers\Concerns;

use ImovelZapAi\Conversations\Application\Actions\SendOutboundMessageAction;
use ImovelZapAi\Conversations\Infrastructure\Persistence\Eloquent\ContactModel;
use ImovelZapAi\Signatures\Domain\Enums\SignatureMode;
use ImovelZapAi\Signatures\Domain\Enums\SignerStatus;
use ImovelZapAi\Signatures\Infrastructure\Persistence\Eloquent\SignatureRequestModel;
use ImovelZapAi\Signatures\Infrastructure\Persistence\Eloquent\SignerModel;
use Illuminate\Support\Collection;

trait NotifiesSignersViaWhatsapp
{
    abstract protected function outboundMessenger(): SendOutboundMessageAction;

    /** @return Collection<int, SignerModel> */
    protected function actableSigners(SignatureRequestModel $request): Collection
    {
        $request->loadMissing('signers');

        $pending = $request->signers->filter(
            fn (SignerModel $signer): bool => $signer->status === SignerStatus::Pending,
        );

        if ($request->mode === SignatureMode::Parallel) {
            return $pending->values();
        }

        $minOrder = $pending->min('order');
        if ($minOrder === null) {
            return collect();
        }

        return $pending->where('order', $minOrder)->values();
    }

    protected function notifySigners(SignatureRequestModel $request): void
    {
        $request->loadMissing(['deal.conversation', 'document.contact']);
        $signerUrls = (array) ($request->meta['signer_urls'] ?? []);
        $conversation = $request->deal?->conversation;

        foreach ($this->actableSigners($request) as $signer) {
            $signer->forceFill(['status' => SignerStatus::Notified])->save();

            $url = $signerUrls[$signer->id] ?? null;
            if ($url === null) {
                continue;
            }

            $contact = $this->resolveSignerContact($signer, $request);
            if ($contact === null) {
                continue;
            }

            try {
                $name = $signer->name ?: ($contact->display_name ?: 'olá');
                $title = $request->title;
                $body = "Olá {$name}! Você precisa assinar o documento \"{$title}\". Acesse pelo link seguro:\n{$url}";

                $this->outboundMessenger()->execute(
                    $request->tenant_id,
                    $contact,
                    $body,
                    $conversation,
                );
            } catch (\Throwable) {
                // Notificação falhou; link permanece válido.
            }
        }
    }

    private function resolveSignerContact(SignerModel $signer, SignatureRequestModel $request): ?ContactModel
    {
        if ($signer->contact_id !== null) {
            $signer->loadMissing('contact');

            return $signer->contact;
        }

        return $request->document?->contact;
    }
}
