<?php

namespace App\Http\Livewire\WireChat\Chat;

use App\Http\Livewire\WireChat\Chats\Chats;
use Illuminate\Support\Facades\Auth;
use Namu\WireChat\Livewire\Chat\Chat as BaseChat;

class Chat extends BaseChat
{

    // This magic accessor will be called for $this->auth
    public function getAuthProperty()
    {
        // Use the active guard from session first, then fallback to checking all guards
        $activeGuard = session('active_guard', 'web');
        $user = Auth::guard($activeGuard)->user();

        if ($user) {
            return $user;
        }

        // Fallback to checking all guards if active guard doesn't have a user
        return Auth::guard('admin')->user()
            ?: Auth::guard('bank')->user()
            ?: Auth::guard('organization')->user()
            ?: Auth::guard('web')->user();
    }

    /**
     * Helper to check authorization and show error toast if unauthorized
     */
    private function checkAuthorization(): bool
    {
        $profile = getActiveProfile();
        if (!$profile) {
            $this->dispatch('wirechat-toast', type: 'error', message: __('Unauthorized access'));
            return false;
        }

        try {
            \App\Helpers\ProfileAuthorizationHelper::authorize($profile);
            return true;
        } catch (\Symfony\Component\HttpKernel\Exception\HttpException $e) {
            $this->dispatch('wirechat-toast', type: 'error', message: __('Unauthorized access'));
            return false;
        }
    }


    /**
     * Override sendMessage to use the correct sendable_id.
     */
    public function sendMessage()
    {
        abort_unless($this->auth(), 401);

        // CRITICAL SECURITY: Validate authorization before sending message
        $profile = getActiveProfile();
        if (!$profile) {
            abort(403, 'No active profile');
        }
        \App\Helpers\ProfileAuthorizationHelper::authorize($profile);

        // rate limit
        $this->rateLimit();

        $attachments = array_merge($this->media, $this->files);

        if (empty($attachments)) {
            $this->validate(['body' => 'required|string']);
        }

        if (count($attachments) != 0) {
            $maxUploads = config('wirechat.attachments.max_uploads');
            $fileMimes = implode(',', config('wirechat.attachments.file_mimes'));
            $fileMaxUploadSize = (int) config('wirechat.attachments.file_max_upload_size');
            $mediaMimes = implode(',', config('wirechat.attachments.media_mimes'));
            $mediaMaxUploadSize = (int) config('wirechat.attachments.media_max_upload_size');

            try {
                $this->validate([
                    'files' => "array|max:$maxUploads|nullable",
                    'files.*' => "max:$fileMaxUploadSize|mimes:$fileMimes",
                    'media' => "array|max:$maxUploads|nullable",
                    'media.*' => "max:$mediaMaxUploadSize|mimes:$mediaMimes",
                ]);
            } catch (\Illuminate\Validation\ValidationException $th) {
                $errors = $th->errors();
                foreach ($errors as $field => $messages) {
                    $this->addError($field, $messages[0]);
                }
                return $this->dispatch('wirechat-toast', type: 'warning', message: $th->getMessage());
            }

            $createdMessages = [];
            foreach ($attachments as $key => $attachment) {
                $path = $attachment->store(
                    \Namu\WireChat\Facades\WireChat::storageFolder(),
                    \Namu\WireChat\Facades\WireChat::storageDisk()
                );

                $replyId = ($key === 0 && $this->replyMessage) ? $this->replyMessage->id : null;

                $message = \Namu\WireChat\Models\Message::create([
                    'reply_id' => $replyId,
                    'conversation_id' => $this->conversation->id,
                    'sendable_type' => $this->auth->getMorphClass(), // Polymorphic sender type
                    'sendable_id' => $this->auth->id, // Polymorphic sender ID
                    'type' => \Namu\WireChat\Enums\MessageType::ATTACHMENT,
                ]);

                $attachment = $message->attachment()->create([
                    'file_path' => $path,
                    'file_name' => basename($path),
                    'original_name' => $attachment->getClientOriginalName(),
                    'mime_type' => $attachment->getMimeType(),
                    'url' => \Storage::disk(\Namu\WireChat\Facades\WireChat::storageDisk())->url($path),
                ]);

                $createdMessages[] = $message;
                $this->conversation->updated_at = now();
                $this->conversation->save();
                $this->dispatch('refresh')->to(Chats::class);
                $this->dispatch('refresh')->to(\App\Http\Livewire\UnreadIndicator::class);
                $this->dispatchMessageCreatedEvent($message);
            }

            foreach ($createdMessages as $key => $message) {
                
                $this->pushMessage($message);
            }
            $this->dispatch('scroll-bottom');
        }

        if ($this->body != null) {
            $createdMessage = \Namu\WireChat\Models\Message::create([
                'reply_id' => $this->replyMessage?->id,
                'conversation_id' => $this->conversation->id,
                'sendable_type' => $this->auth->getMorphClass(), // Polymorphic sender type
                'sendable_id' => $this->auth->id, // Polymorphic sender ID
                'body' => $this->body,
                'type' => \Namu\WireChat\Enums\MessageType::TEXT,
            ]);

            $this->pushMessage($createdMessage);
            $this->conversation->touch();
            $this->dispatchMessageCreatedEvent($createdMessage);
            $this->dispatch('refresh')->to(Chats::class);
            $this->dispatch('refreshList')->to(Chats::class);

            // Also dispatch to UnreadIndicator to update the red dot
            $this->dispatch('refresh')->to(\App\Http\Livewire\UnreadIndicator::class);

        }

        $this->reset('media', 'files', 'body');
        $this->dispatch('scroll-bottom');
        
        $this->removeReply();
    }


    private function pushMessage(\Namu\WireChat\Models\Message $message)
    {
        $groupKey = $this->messageGroupKey($message);

        // Ensure loadedMessages is a Collection
        $this->loadedMessages = collect($this->loadedMessages);

        // Use tap to create a new group if it doesn’t exist, then push the message
        $this->loadedMessages->put($groupKey, $this->loadedMessages->get($groupKey, collect())->push($message));
    }


    private function messageGroupKey(\Namu\WireChat\Models\Message $message): string
    {
        $messageDate = $message->created_at;
        $groupKey = '';
        if ($messageDate->isToday()) {
            $groupKey = __('wirechat::chat.message_groups.today');
        } elseif ($messageDate->isYesterday()) {
            $groupKey = __('wirechat::chat.message_groups.yesterday');
        } elseif ($messageDate->greaterThanOrEqualTo(now()->subDays(7))) {
            $groupKey = $messageDate->format('l'); // Day name
        } else {
            $groupKey = $messageDate->format('d/m/Y'); // Older than 7 days, dd/mm/yyyy
        }

        return $groupKey;
    }



    /**
     * Keep a message from auto-deletion (mark as kept)
     */
    public function keepMessage(string $id): void
    {
        if (!$this->checkAuthorization()) {
            return;
        }

        if (!$this->auth()) {
            $this->dispatch('wirechat-toast', type: 'error', message: __('Unauthorized access'));
            return;
        }

        $id = decrypt($id);
        $message = \Namu\WireChat\Models\Message::findOrFail($id);

        // Verify user belongs to the conversation
        if (!$this->auth->belongsToConversation($message->conversation)) {
            $this->dispatch('wirechat-toast', type: 'error', message: __('Unauthorized access'));
            return;
        }

        // Check if disappearing messages is enabled and allow_users_to_keep is true
        if (!timebank_config('wirechat.disappearing_messages.enabled', true) ||
            !timebank_config('wirechat.disappearing_messages.allow_users_to_keep', true)) {
            return;
        }

        // Toggle kept status
        if ($message->kept_at) {
            // Unkeep the message
            $message->kept_at = null;
        } else {
            // Keep the message
            $message->kept_at = now();
        }

        $message->save();

        // Update the message in loadedMessages collection to trigger Livewire re-render
        if ($this->loadedMessages) {
            $this->loadedMessages = collect($this->loadedMessages)->map(function ($messageGroup) use ($message) {
                return $messageGroup->map(function ($loadedMessage) use ($message) {
                    if ($loadedMessage->id === $message->id) {
                        $loadedMessage->kept_at = $message->kept_at;
                    }
                    return $loadedMessage;
                });
            });
        }
    }

    /**
     * Delete conversation (override with authorization)
     */
    public function deleteConversation()
    {
        if (!$this->checkAuthorization()) {
            return;
        }

        return parent::deleteConversation();
    }

    /**
     * Clear conversation history (override with authorization)
     */
    public function clearConversation()
    {
        if (!$this->checkAuthorization()) {
            return;
        }

        return parent::clearConversation();
    }

    /**
     * Exit conversation (override with authorization)
     */
    public function exitConversation()
    {
        if (!$this->checkAuthorization()) {
            return;
        }

        return parent::exitConversation();
    }

    /**
     * Delete message for me (override with authorization)
     */
    public function deleteForMe(string $id): void
    {
        if (!$this->checkAuthorization()) {
            return;
        }

        parent::deleteForMe($id);
    }

    /**
     * Delete message for everyone (override with authorization)
     */
    public function deleteForEveryone(string $id): void
    {
        if (!$this->checkAuthorization()) {
            return;
        }

        parent::deleteForEveryone($id);
    }

    /**
     * Send like (override with authorization)
     */
    public function sendLike()
    {
        if (!$this->checkAuthorization()) {
            return;
        }

        return parent::sendLike();
    }

    /**
     * Set reply (override with authorization)
     */
    public function setReply(string $id): void
    {
        if (!$this->checkAuthorization()) {
            return;
        }

        parent::setReply($id);
    }

    /**
     * Mount component (override with authorization)
     */
    public function mount($conversation = null)
    {
        // CRITICAL SECURITY: Validate authorization on mount
        $profile = getActiveProfile();
        if (!$profile) {
            abort(403, 'No active profile');
        }
        \App\Helpers\ProfileAuthorizationHelper::authorize($profile);

        return parent::mount($conversation);
    }

    public function render()
    {
        // CRITICAL SECURITY: Re-validate authorization on every render
        $profile = getActiveProfile();
        if (!$profile) {
            return view('errors.unauthorized-component');
        }

        try {
            \App\Helpers\ProfileAuthorizationHelper::authorize($profile);
        } catch (\Symfony\Component\HttpKernel\Exception\HttpException $e) {
            return view('errors.unauthorized-component');
        }

        return parent::render();
    }

}
