<?php

namespace App\Actions\Communications;

use App\Enum\Communication\PhoneNumberTypeSlug;
use App\Models\Communication\SolicitorPhoneNumber;
use Illuminate\Database\Eloquent\Model;
use RuntimeException;

class ResolveOutboundPhoneNumberAction
{
    public function handle(int $solicitorId, Model $target): SolicitorPhoneNumber
    {
        $preferredSlug = $this->resolvePreferredPhoneNumberTypeSlug($target);

        $number = $this->findPrimaryActiveNumberBySlug($solicitorId, $preferredSlug)
            ?? $this->findAnyDefaultOutboundNumber($solicitorId)
            ?? $this->findFirstActiveNumber($solicitorId);

        if (! $number) {
            throw new RuntimeException(
                "No active outbound phone number could be resolved for solicitor [{$solicitorId}]."
            );
        }

        return $number->loadMissing('type');
    }

    protected function resolvePreferredPhoneNumberTypeSlug(Model $target): string
    {
        $callableType = $this->resolveCallableType($target);

        return match ($callableType) {
            'client', 'contact', 'lead' => PhoneNumberTypeSlug::ClientLine->value,
            'institution', 'insurer', 'authority', 'defendant', 'respondent' => PhoneNumberTypeSlug::ExternalLine->value,
            default => PhoneNumberTypeSlug::ClientLine->value,
        };
    }

    protected function resolveCallableType(Model $target): string
    {
        if (method_exists($target, 'getCallableType')) {
            return (string) $target->getCallableType();
        }

        return strtolower(class_basename($target));
    }

    protected function findPrimaryActiveNumberBySlug(int $solicitorId, string $slug): ?SolicitorPhoneNumber
    {
        return SolicitorPhoneNumber::query()
            ->with('type')
            ->where('solicitor_id', $solicitorId)
            ->where('is_active', true)
            ->whereHas('type', function ($query) use ($slug) {
                $query->where('slug', $slug);
            })
            ->orderByDesc('is_primary')
            ->orderBy('id')
            ->first();
    }

    protected function findAnyDefaultOutboundNumber(int $solicitorId): ?SolicitorPhoneNumber
    {
        return SolicitorPhoneNumber::query()
            ->with('type')
            ->where('solicitor_id', $solicitorId)
            ->where('is_active', true)
            ->whereHas('type', function ($query) {
                $query->where('is_default_outbound', true)
                    ->where('is_active', true);
            })
            ->orderByDesc('is_primary')
            ->orderBy('id')
            ->first();
    }

    protected function findFirstActiveNumber(int $solicitorId): ?SolicitorPhoneNumber
    {
        return SolicitorPhoneNumber::query()
            ->with('type')
            ->where('solicitor_id', $solicitorId)
            ->where('is_active', true)
            ->orderByDesc('is_primary')
            ->orderBy('id')
            ->first();
    }
}