<?php

namespace App\Components\Dialler;

use App\Actions\Communications\StartOutboundCallAction;
use App\Models\Client\Client;
use Livewire\Attributes\Computed;
use Livewire\Attributes\On;
use Livewire\Component;

/**
 * CallInstitute — per-client panel for calling a DSAR institution contact.
 *
 * Mirrors CallManager, but the dialled target is an institution contact while the
 * Client stays the communicable — so the call still shows in the client's activity
 * feed and ties to their claim. Selection is two-step: pick the DSAR institution,
 * then pick which contact / number to dial. The in-call experience (ringing,
 * connected, wrap-up) is handled by the global CallOverlay, same as a client call.
 */
class CallInstitute extends Component {
    public Client $client;

    public ?int    $selectedInstitutionId = null;
    public ?string $selectedContactKey    = null;   // "{contactId}:{telephone|mobile}"

    // Device status (gates the dial button) — synced from the global Twilio bootstrap.
    public bool    $deviceReady       = false;
    public bool    $deviceRegistering = false;
    public ?string $errorMessage      = null;

    public function mount(Client $client): void
    {
        $this->client = $client;
    }

    public function updatedSelectedInstitutionId(): void
    {
        $this->selectedContactKey = null;
        $this->errorMessage       = null;
    }

    // ── Outbound institution call ─────────────────────────────────────────────

    public function callInstitution(StartOutboundCallAction $action): void
    {
        abort_unless(auth()->user()?->can('communications.call.institution'), 403);

        if (! $this->deviceReady) {
            $this->errorMessage = 'The browser phone is not ready yet.';
            return;
        }

        $this->errorMessage = null;

        // Re-resolve the institution from the client's own DSAR institutions — never
        // trust the posted id (it could reference an institution in another claim).
        $institution = $this->institutions->firstWhere('id', (int) $this->selectedInstitutionId);

        if (! $institution) {
            $this->errorMessage = 'Please choose a DSAR institution.';
            return;
        }

        [$contactId, $numberField] = array_pad(explode(':', (string) $this->selectedContactKey, 2), 2, null);

        $contact = $institution->contacts->firstWhere('id', (int) $contactId);

        if (! $contact || ! in_array($numberField, ['telephone', 'mobile'], true)) {
            $this->errorMessage = 'Please choose a contact number to dial.';
            return;
        }

        $number = $numberField === 'telephone'
            ? (string) ($contact->telephone ?? '')
            : (string) ($contact->mobile ?? '');

        if (trim($number) === '') {
            $this->errorMessage = 'That contact has no usable number.';
            return;
        }

        $label = $contact->name
            ? $institution->display_name . ' — ' . $contact->name
            : $institution->display_name;

        try {
            $communication = $action->handle(
                subject:     $this->client,         // the Client stays the communicable
                toNumber:    $number,
                targetLabel: $label,
                targetType:  'institution',
                callType:    'institution',
                claimId:     $this->client->claim?->id,
                solicitorId: $this->client->solicitor_id,
                uiOrigin:    'contact_hub_institution',
            );

            // Hand the call to the global CallOverlay, then connect via the SDK.
            $this->dispatch('dialler-call-started',
                communication_id: $communication->id,
                call_id:          $communication->call->id,
                label:            $label,
                direction:        'outbound',
            );

            $this->dispatch('twilio-start-browser-call', call_id: $communication->call->id);

        } catch (\Throwable $e) {
            $this->errorMessage = $e->getMessage();
            report($e);
        }
    }

    // ── Device events (gate the dial button) ─────────────────────────────────

    #[On('twilio-device-registering')]
    public function handleDeviceRegistering(): void
    {
        $this->deviceRegistering = true;
        $this->deviceReady       = false;
    }

    #[On('twilio-device-registered')]
    public function handleDeviceRegistered(): void
    {
        $this->deviceRegistering = false;
        $this->deviceReady       = true;
    }

    #[On('twilio-device-unregistered')]
    public function handleDeviceUnregistered(): void
    {
        $this->deviceRegistering = false;
        $this->deviceReady       = false;
    }

    #[On('twilio-device-error')]
    public function handleDeviceError($message = null): void
    {
        $this->deviceRegistering = false;
        $this->deviceReady       = false;
    }

    // ── Computed ──────────────────────────────────────────────────────────────

    #[Computed]
    public function institutions()
    {
        return $this->client->claim?->dsars()
            ->with('institution.contacts')
            ->get()
            ->pluck('institution')
            ->filter()
            ->unique('id')
            ->values()
            ?? collect();
    }

    #[Computed]
    public function institutionContacts(): array
    {
        if (! $this->selectedInstitutionId) {
            return [];
        }

        $institution = $this->institutions->firstWhere('id', (int) $this->selectedInstitutionId);

        if (! $institution) {
            return [];
        }

        $options = [];

        foreach ($institution->contacts as $contact) {
            $name = $contact->name ?: 'Contact';

            // telephone is a UK PhoneNumber value object (or null); mobile is raw.
            if ($contact->telephone) {
                $options[] = [
                    'key'   => $contact->id . ':telephone',
                    'label' => $name . ' · ' . $contact->telephone->toNational() . ' (Tel)',
                ];
            }

            $mobile = trim((string) ($contact->mobile ?? ''));
            if ($mobile !== '') {
                $options[] = [
                    'key'   => $contact->id . ':mobile',
                    'label' => $name . ' · ' . $mobile . ' (Mobile)',
                ];
            }
        }

        return $options;
    }

    public function render()
    {
        return view('components.dialler.call-institute');
    }
}
