<?php

namespace App\Components\Contact;

use App\Actions\Communications\AssertCanContactAction;
use App\Enum\Contact\MessageChannel;
use App\Jobs\Synapse\AutoTranscribeRecordingJob;
use App\Jobs\Synapse\ClassifyAndScoreCallJob;
use App\Models\Communication\Communication;
use App\Models\Communication\Recording;
use App\Models\Claim\Claim;
use App\Models\Client\Client;
use App\Models\Contact\ContactTemplate;
use App\Models\Contact\Hub\ContactMessage;
use App\Jobs\DownloadAndStoreRecordingJob;
use Illuminate\Database\Eloquent\Model;
use Livewire\Attributes\On;
use Livewire\Component;

class ContactHub extends Component
{
    public Model $model;

    public ?string $filterChannel = null;   // null | 'email' | 'sms' | 'call'
    public ?string $filterStatus  = null;

    /** Message currently shown in the detail offcanvas (null = closed). */
    public ?int $selectedMessageId = null;

    public function mount(Model $model): void
    {
        $this->model = $model;
    }

    #[On('contactMessageSent')]
    #[On('contactMessageQueued')]
    #[On('dialler-call-started')]
    #[On('twilio-call-disconnected')]
    public function refreshFeed(): void
    {
        // Empty — re-render is triggered by the attribute.
    }

    public function viewMessage(int $id): void
    {
        $this->selectedMessageId = $id;
    }

    public function retranscribeRecording(int $recordingId): void
    {
        AutoTranscribeRecordingJob::dispatch($recordingId);
    }

    public function reclassifyRecording(int $recordingId): void
    {
        ClassifyAndScoreCallJob::dispatch($recordingId, true);
    }

    public function refetchRecording(int $recordingId): void
    {
        $recording = Recording::query()->findOrFail($recordingId);

        $recording->update([
            'storage_disk' => null,
            'storage_path' => null,
        ]);
        
        DownloadAndStoreRecordingJob::dispatch($recording->id);

        $this->dispatch('notify', message: 'Recording re-fetch has been queued.');
    }

    public function render()
    {
        $check = app(AssertCanContactAction::class);

        $emailValidity = $check(MessageChannel::EMAIL, $this->model);
        $smsValidity   = $check(MessageChannel::SMS,   $this->model);

        $relatedClaim = method_exists($this->model, 'claim') ? $this->model->claim : null;
        $claim = $this->model instanceof Claim ? $this->model : $relatedClaim;

        $morphTypes = array_unique(array_filter([
            $this->model->getMorphClass(),
            get_class($this->model),
            $relatedClaim?->getMorphClass(),
            $relatedClaim ? get_class($relatedClaim) : null,
        ]));

        $templates = ContactTemplate::query()
            ->where('is_active', true)
            ->where('allow_manual_send', true)
            ->where(function ($q) use ($morphTypes) {
                $q->whereNull('applies_to_type')
                  ->orWhereIn('applies_to_type', $morphTypes);
            })
            ->orderBy('channel')
            ->orderBy('name')
            ->get()
            ->groupBy(fn ($t) => $t->channel->value);

        $fetchCalls     = $this->filterChannel === null || $this->filterChannel === 'call';
        $fetchMessages  = $this->filterChannel === null || $this->filterChannel === 'email' || $this->filterChannel === 'sms';

        $calls = $fetchCalls
            ? Communication::query()
                ->where('communicable_type', $this->model->getMorphClass())
                ->where('communicable_id',   $this->model->getKey())
                ->with(['call', 'agent', 'recordings.synapseTranscript', 'recordings.callScore'])
                ->latest('started_at')
                ->limit(20)
                ->get()
                ->map(fn ($c) => ['kind' => 'call', 'at' => $c->started_at ?? $c->created_at, 'data' => $c])
            : collect();

        $messages = $fetchMessages
            ? ContactMessage::query()
                ->forMessageable($this->model)
                ->when(
                    $this->filterChannel && $this->filterChannel !== 'call',
                    fn ($q) => $q->where('channel', $this->filterChannel)
                )
                ->when($this->filterStatus, fn ($q) => $q->where('status', $this->filterStatus))
                ->with(['template', 'creator'])
                ->latest()
                ->limit(20)
                ->get()
                ->map(fn ($m) => ['kind' => 'message', 'at' => $m->created_at, 'data' => $m])
            : collect();

        $activities = $calls->concat($messages)
            ->sortByDesc('at')
            ->take(30)
            ->values();

        $selectedMessage = $this->selectedMessageId
            ? ContactMessage::with(['template', 'creator', 'events', 'attachments'])->find($this->selectedMessageId)
            : null;

        return view('components.contact.contact-hub', [
            'emailValidity'   => $emailValidity,
            'smsValidity'     => $smsValidity,
            'activities'      => $activities,
            'templates'       => $templates,
            'claim'           => $claim,
            'selectedMessage' => $selectedMessage,
        ]);
    }
}
