<?php

namespace App\Components\Contact;

use App\Enum\Contact\MessageChannel;
use App\Enum\Contact\MessageDirection;
use App\Enum\Contact\MessageProvider;
use App\Enum\Contact\MessageStatus;
use App\Jobs\Contact\SendContactMessageJob;
use App\Models\Contact\ContactTemplate;
use App\Models\Contact\Hub\ContactMessage;
use App\Models\Solicitor\Solicitor;
use App\Models\Solicitor\SolicitorEmailSender;
use App\Services\Communications\Placeholders\TemplateRenderer;
use App\ValueObjects\Communications\PlaceholderContext;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Attributes\Computed;
use Livewire\Component;

class InboxReplyPanel extends Component
{
    use AuthorizesRequests;

    public int $messageId;

    // Form fields
    public string $to       = '';
    public string $subject  = '';
    public ?int   $senderId  = null;
    public ?int   $templateId = null;
    public string $bodyHtml  = '';   // synced from Alpine contenteditable before send

    // State
    public bool    $sent  = false;
    public ?string $error = null;

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

        $message = ContactMessage::where('id', $this->messageId)
            ->where('solicitor_id', app(Solicitor::class)->id)
            ->firstOrFail();

        $this->to      = $message->from_email ?? '';
        // Avoid stacking Re: Re: Re:
        $this->subject = 'Re: ' . preg_replace('/^(re:\s*)+/i', '', trim($message->subject ?? ''));

        $this->senderId = SolicitorEmailSender::where('solicitor_id', app(Solicitor::class)->id)
            ->orderByDesc('is_default')
            ->value('id');
    }

    #[Computed]
    public function senders()
    {
        return SolicitorEmailSender::where('solicitor_id', app(Solicitor::class)->id)
            ->orderByDesc('is_default')
            ->orderBy('email_address')
            ->get();
    }

    #[Computed]
    public function signature(): ?string
    {
        if (!$this->senderId) {
            return null;
        }
        return SolicitorEmailSender::find($this->senderId)?->signatureHtml();
    }

    #[Computed]
    public function templates()
    {
        return ContactTemplate::where('solicitor_id', app(Solicitor::class)->id)
            ->where('channel', MessageChannel::EMAIL->value)
            ->where('is_active', true)
            ->where('allow_manual_send', true)
            ->orderBy('name')
            ->get(['id', 'name', 'applies_to_type']);
    }

    public function applyTemplate(): void
    {
        if (!$this->templateId) {
            return;
        }

        $rendered = $this->renderCurrentTemplate();

        if ($rendered->subject) {
            $this->subject = $rendered->subject;
        }

        $this->dispatch('ct-template-applied', bodyHtml: $rendered->bodyHtml ?? $rendered->bodyText ?? '');
    }

    public function previewTemplate(): void
    {
        if (!$this->templateId) {
            return;
        }

        $rendered = $this->renderCurrentTemplate();

        $this->dispatch('ct-template-preview',
            subject: $rendered->subject ?? '(no subject)',
            bodyHtml: $rendered->bodyHtml ?? nl2br(e($rendered->bodyText ?? '')),
            unknownPlaceholders: $rendered->unknownPlaceholders,
        );
    }

    private function renderCurrentTemplate(): \App\ValueObjects\Communications\RenderedMessage
    {
        $solicitorId = app(Solicitor::class)->id;

        $template = ContactTemplate::where('solicitor_id', $solicitorId)
            ->findOrFail($this->templateId);

        $inbound = ContactMessage::where('id', $this->messageId)
            ->where('solicitor_id', $solicitorId)
            ->with('messageable')
            ->firstOrFail();

        $sender = $this->senderId
            ? SolicitorEmailSender::where('solicitor_id', $solicitorId)->find($this->senderId)
            : null;

        $ctx = PlaceholderContext::fromMessageable(
            messageable: $inbound->messageable,
            solicitor: app(Solicitor::class),
            user: auth()->user(),
            sender: $sender,
        );

        return app(TemplateRenderer::class)->render($template, $ctx);
    }

    public function send(): void
    {
        $this->error = null;
        $this->sent  = false;

        $this->validate([
            'to'       => ['required', 'email', 'max:255'],
            'subject'  => ['required', 'string', 'max:255'],
            'senderId' => ['required', 'integer'],
            'bodyHtml' => ['required', 'string', 'min:1'],
        ]);

        $solicitorId = app(Solicitor::class)->id;

        $inbound = ContactMessage::where('id', $this->messageId)
            ->where('solicitor_id', $solicitorId)
            ->firstOrFail();

        $sender = SolicitorEmailSender::where('solicitor_id', $solicitorId)
            ->findOrFail($this->senderId);

        // Append signature below a rule
        $sig  = $sender->signatureHtml();
        $body = $this->bodyHtml;
        if ($sig) {
            $body .= '<br><hr style="border:none;border-top:1px solid #dee2e6;margin:16px 0;">' . $sig;
        }

        $bodyText = strip_tags(
            str_replace(['<br>', '<br/>', '<br />', '</p>', '</div>', '</li>'], "\n", $body)
        );

        try {
            $reply = ContactMessage::create([
                'solicitor_id'            => $solicitorId,
                'channel'                 => MessageChannel::EMAIL,
                'direction'               => MessageDirection::OUTBOUND,
                'provider'                => MessageProvider::SENDGRID,
                'status'                  => MessageStatus::QUEUED,
                'sender_email_id'         => $sender->id,
                'sender_display'          => $sender->display_name,
                'sender_value'            => $sender->email_address,
                'recipient_email'         => $this->to,
                'subject'                 => $this->subject,
                'body_html'               => $body,
                'body_text'               => trim($bodyText),
                'template_id'             => $this->templateId ?: null,
                'messageable_type'        => $inbound->messageable_type,
                'messageable_id'          => $inbound->messageable_id,
                'in_reply_to_provider_id' => $inbound->provider_message_id,
                'thread_key'              => $inbound->thread_key,
                'created_by'              => auth()->id(),
                'queued_at'               => now(),
            ]);

            SendContactMessageJob::dispatch($reply->id);

            $this->sent     = true;
            $this->bodyHtml = '';
            $this->dispatch('reply-sent');

        } catch (\Throwable $e) {
            $this->error = 'Failed to send: ' . $e->getMessage();
            report($e);
        }
    }

    public function render()
    {
        return view('components.contact.inbox-reply-panel', [
            'senders'   => $this->senders,
            'signature' => $this->signature,
            'templates' => $this->templates,
        ]);
    }
}
