<?php

namespace App\Components\Contact;

use App\Jobs\Synapse\ClassifyInboundEmailJob;
use App\Models\Contact\Hub\ContactMessage;
use App\Models\Contact\Hub\ContactMessageAttachment;
use App\Models\Solicitor\Solicitor;
use App\Models\Solicitor\SolicitorEmailSender;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;

class InboxIndex extends Component
{
    use AuthorizesRequests, WithPagination;

    #[Url]
    public ?int $senderId = null;

    #[Url]
    public ?int $messageId = null;

    #[Url]
    public string $search = '';

    /**
     * Classification filter.
     * '' = all | 'dsar_response' | 'dsar_matched' | 'dsar_unmatched' | 'generic' | 'unclassified'
     */
    #[Url(as: 'filter')]
    public string $classificationFilter = '';

    public function mount(): void
    {
        $this->authorize('inbox.view');

        if (!$this->senderId) {
            $first = $this->senders()->first();
            $this->senderId = $first?->id;
        }
    }

    public function selectSender(int $id): void
    {
        $this->senderId = $id;
        $this->messageId = null;
        $this->search = '';
        $this->classificationFilter = '';
        $this->resetPage();
    }

    public function setClassificationFilter(string $filter): void
    {
        $this->classificationFilter = $filter;
        $this->messageId = null;
        $this->resetPage();
    }

    public function openMessage(int $id): void
    {
        $this->messageId = $id;

        ContactMessage::where('id', $id)
            ->whereNull('read_at')
            ->update(['read_at' => now()]);
    }

    public function markUnread(int $id): void
    {
        ContactMessage::where('id', $id)->update(['read_at' => null]);

        if ($this->messageId === $id) {
            $this->messageId = null;
        }
    }

    public function updatedSearch(): void
    {
        $this->resetPage();
        $this->messageId = null;
    }

    public function updatedClassificationFilter(): void
    {
        $this->resetPage();
        $this->messageId = null;
    }

    public function reclassify(int $id): void
    {
        ClassifyInboundEmailJob::dispatch($id, force: true);
    }

    public function saveAttachmentNote(int $attachmentId, string $text): void
    {
        $attachment = ContactMessageAttachment::whereHas('message', function ($q) {
            $q->where('solicitor_id', app(Solicitor::class)->id);
        })->findOrFail($attachmentId);

        $attachment->update([
            'extracted_text'    => trim($text),
            'extraction_status' => 'manual',
        ]);
    }

    public function senders()
    {
        $solicitorId = app(Solicitor::class)->id;

        return SolicitorEmailSender::where('solicitor_id', $solicitorId)
            ->withCount([
                'inboundMessages as unread_count' => fn ($q) => $q->whereNull('read_at'),
            ])
            ->orderByDesc('is_default')
            ->orderBy('email_address')
            ->get();
    }

    public function render()
    {
        $senders = $this->senders();

        $messages = $this->senderId
            ? ContactMessage::inbound()
                ->where('sender_email_id', $this->senderId)
                ->withCount('attachments')
                ->when($this->search, fn ($q) => $q->where(function ($q) {
                    $q->where('subject', 'like', "%{$this->search}%")
                      ->orWhere('from_email', 'like', "%{$this->search}%")
                      ->orWhere('body_text', 'like', "%{$this->search}%");
                }))
                ->when($this->classificationFilter, function ($q) {
                    match ($this->classificationFilter) {
                        'dsar_response'  => $q->where('classification', 'dsar_response'),
                        'dsar_matched'   => $q->where('classification', 'dsar_response')->whereNotNull('messageable_type'),
                        'dsar_unmatched' => $q->where('classification', 'dsar_response')->whereNull('messageable_type'),
                        'generic'        => $q->where('classification', 'generic'),
                        'unclassified'   => $q->whereNull('classification'),
                        default          => null,
                    };
                })
                ->orderByDesc('created_at')
                ->paginate(25)
            : collect();

        $openMessage = $this->messageId
            ? ContactMessage::with('attachments')->find($this->messageId)
            : null;

        return view('components.contact.inbox-index', [
            'senders'     => $senders,
            'messages'    => $messages,
            'openMessage' => $openMessage,
        ]);
    }
}
