<?php

namespace App\Http\Livewire;

use Illuminate\Support\Facades\Lang;
use Livewire\Component;
use Namu\WireChat\Events\NotifyParticipant;
use WireUi\Traits\WireUiActions;

class ReserveButton extends Component
{
    use WireUiActions;
    public $post;
    public $activeProfile;
    public $hasReserved = false;
    public $reservationCount = 0;
    public $canReserve = false;
    public $disabledReason = null;
    public $showConfirmModal = false;
    public $showCancelModal = false;
    public $showReservationsModal = false;
    public $reservationsByType = [];
    public $isOrganizer = false;
    public $messageToReserved = '';
    public $isGuest = false;

    public function mount($post)
    {
        $this->post = $post;
        $this->activeProfile = getActiveProfile();
        $this->isGuest = !$this->activeProfile;

        // Ensure meeting is loaded
        if (!$this->post->relationLoaded('meeting')) {
            $this->post->load('meeting');
        }

        // Get reservation count
        if ($this->post && method_exists($this->post, 'loveReactant')) {
            $reactant = $this->post->getLoveReactant();
            if ($reactant) {
                $reactionType = \Cog\Laravel\Love\ReactionType\Models\ReactionType::fromName('Reserve');
                if ($reactionType) {
                    $this->reservationCount = $reactant->getReactionCounterOfType($reactionType)?->count ?? 0;
                }
            }
        }

        $this->checkReservationPermissions();
        $this->checkIfReserved();
        $this->loadReservations();
    }

    private function loadReservations()
    {
        // Only load if current profile is the organizer of the meeting
        if (!$this->post || !isset($this->post->meeting)) {
            return;
        }

        $this->isOrganizer = session('activeProfileType') === $this->post->meeting->meetingable_type
                    && session('activeProfileId') === $this->post->meeting->meetingable_id;

        if (!$this->isOrganizer) {
            return;
        }

        // Get all reacters for this post with Reserve reaction
        $reactionType = \Cog\Laravel\Love\ReactionType\Models\ReactionType::fromName('Reserve');
        if (!$reactionType) {
            return;
        }

        $reactions = \Cog\Laravel\Love\Reaction\Models\Reaction::where('reactant_id', $this->post->love_reactant_id)
            ->where('reaction_type_id', $reactionType->getId())
            ->get();

        $groupedReactions = [
            'App\\Models\\User' => [],
            'App\\Models\\Organization' => [],
            'App\\Models\\Bank' => [],
            'App\\Models\\Admin' => [],
        ];

        foreach ($reactions as $reaction) {
            $reacter = $reaction->reacter;
            if ($reacter) {
                $reacterable = $reacter->reacterable;
                if ($reacterable) {
                    $type = get_class($reacterable);
                    if (isset($groupedReactions[$type])) {
                        $groupedReactions[$type][] = $reacterable;
                    }
                }
            }
        }

        $this->reservationsByType = $groupedReactions;
    }

    private function checkReservationPermissions()
    {
        // Check if reserve reaction is enabled in config
        if (!timebank_config('reactions.reserve.enabled', false)) {
            $this->canReserve = false;
            $this->disabledReason = 'reaction_disabled';
            return;
        }

        // Admins cannot reserve
        if ($this->activeProfile instanceof \App\Models\Admin) {
            $this->canReserve = false;
            $this->disabledReason = 'admin_cannot_reserve';
            return;
        }

        // Profile must be registered as love reacter
        if (
            !$this->activeProfile ||
            !method_exists($this->activeProfile, 'isRegisteredAsLoveReacter') ||
            !$this->activeProfile->isRegisteredAsLoveReacter()
        ) {
            $this->canReserve = false;
            $this->disabledReason = 'not_registered_reacter';
            return;
        }

        // Check if post has a meeting
        if (!$this->post || !isset($this->post->meeting)) {
            $this->canReserve = false;
            $this->disabledReason = 'no_meeting';
            return;
        }

        $this->canReserve = true;
        $this->disabledReason = null;
    }

    private function checkIfReserved()
    {
        if (!$this->canReserve || !$this->activeProfile->isRegisteredAsLoveReacter()) {
            $this->hasReserved = false;
            return;
        }

        $this->hasReserved = $this->activeProfile
            ->viaLoveReacter()
            ->hasReactedTo($this->post, 'Reserve');
    }

    public function redirectToLogin()
    {
        // Get the referrer URL (the page the user is viewing)
        $intendedUrl = request()->header('Referer');

        // Store as intended URL
        if ($intendedUrl) {
            session(['url.intended' => $intendedUrl]);
        }

        return redirect()->route('login');
    }

    public function openConfirmModal()
    {
        $this->showConfirmModal = true;
    }

    public function openCancelModal()
    {
        $this->showCancelModal = true;
    }

    public function openReservationsModal()
    {
        // Security check: only organizer can view
        if (!$this->isOrganizer) {
            return;
        }

        $this->showReservationsModal = true;
    }

    public function confirmReservation()
    {
        $this->showConfirmModal = false;

        if (!$this->canReserveSecurityCheck()) {
            return;
        }

        if ($this->hasReserved) {
            return;
        }

        try {
            $this->activeProfile->viaLoveReacter()->reactTo($this->post, 'Reserve');

            // Update state
            $this->hasReserved = true;

            // Refresh count from database
            $reactionType = \Cog\Laravel\Love\ReactionType\Models\ReactionType::fromName('Reserve');
            if ($reactionType) {
                $this->reservationCount = $this->post->getLoveReactant()->getReactionCounterOfType($reactionType)?->count ?? 0;
            }

            \Log::info('Reservation added. hasReserved: ' . ($this->hasReserved ? 'true' : 'false') . ', count: ' . $this->reservationCount);

            // Reload reservations list
            $this->loadReservations();
        } catch (\Exception $e) {
            \Log::error('Failed to add reservation: ' . $e->getMessage());
            session()->flash('error', __('Failed to add reservation. Please try again.'));
        }
    }

    public function confirmCancellation()
    {
        $this->showCancelModal = false;

        if (!$this->canReserveSecurityCheck()) {
            return;
        }

        if (!$this->hasReserved) {
            return;
        }

        try {
            $this->activeProfile->viaLoveReacter()->unReactTo($this->post, 'Reserve');
            $this->reservationCount = max(0, $this->reservationCount - 1);
            $this->hasReserved = false;

            // Reload reservations list
            $this->loadReservations();
        } catch (\Exception $e) {
            \Log::error('Failed to remove reservation: ' . $e->getMessage());
            session()->flash('error', __('Failed to cancel reservation. Please try again.'));
        }
    }

    private function canReserveSecurityCheck()
    {
        if (!$this->post || !isset($this->post->meeting)) {
            return false;
        }

        if (!timebank_config('reactions.reserve.enabled', false)) {
            return false;
        }

        if ($this->activeProfile instanceof \App\Models\Admin) {
            return false;
        }

        if (
            !method_exists($this->activeProfile, 'isRegisteredAsLoveReacter') ||
            !$this->activeProfile->isRegisteredAsLoveReacter()
        ) {
            return false;
        }

        return true;
    }

    public function sendMessageToReserved()
    {
        // Security check: only organizer can send messages
        if (!$this->isOrganizer) {
            return;
        }

        // Validate the message
        $this->validate([
            'messageToReserved' => 'required|string|max:300',
        ]);

        // Strip HTML tags for security
        $cleanMessage = strip_tags($this->messageToReserved);

        // Get the send delay configuration (same as bulk mail)
        $sendDelay = timebank_config('bulk_mail.send_delay_seconds', 2);

        // Get all reserved participants
        $allReserved = [];
        foreach ($this->reservationsByType as $type => $reacters) {
            $allReserved = array_merge($allReserved, $reacters);
        }

        // Get the organizer profile
        $organizer = getActiveProfile();

        // Create group chat with all participants
        // Get organizer's locale for group name
        $groupLocale = $organizer->lang_preference ?? config('app.fallback_locale');

        // Get post title for group name with fallback logic
        $groupPostTranslation = $this->post->translations->where('locale', $groupLocale)->first();
        if (!$groupPostTranslation) {
            $fallbackLocale = config('app.fallback_locale');
            $groupPostTranslation = $this->post->translations->where('locale', $fallbackLocale)->first();
        }
        if (!$groupPostTranslation) {
            $groupPostTranslation = $this->post->translations->first();
        }
        $groupName = $groupPostTranslation ? $groupPostTranslation->title : 'Event ' . $this->post->id;

        // Create group conversation
        $groupConversation = $organizer->createGroup(
            name: $groupName,
            description: trans('messages.Reservation_update', [], $groupLocale)
        );

        // Add all participants to the group (skip organizer as they're already added)
        foreach ($allReserved as $reacter) {
            // Skip if this is the organizer (already added when creating group)
            if (get_class($reacter) === get_class($organizer) && $reacter->id === $organizer->id) {
                continue;
            }

            $groupConversation->addParticipant($reacter);
        }

        // Construct the chat message using organizer's locale
        $chatMessage = $groupName . ' ' . __('update', [], $groupLocale) . ':' . PHP_EOL . PHP_EOL . $cleanMessage;

        // Send message to the group
        $message = $organizer->sendMessageTo($groupConversation, $chatMessage);

        // Broadcast to all participants for real-time notifications
        foreach ($allReserved as $reacter) {
            broadcast(new NotifyParticipant($reacter, $message));
        }

        // Dispatch email jobs with delays
        $delay = 0;
        foreach ($allReserved as $reacter) {
            \App\Jobs\SendReservationUpdateMail::dispatch($reacter, $this->post, $cleanMessage, $organizer)
                ->delay(now()->addSeconds($delay))
                ->onQueue('emails');

            $delay += $sendDelay;
        }

        // Also send a copy to the organizer
        \App\Jobs\SendReservationUpdateMail::dispatch($organizer, $this->post, $cleanMessage, $organizer)
            ->delay(now()->addSeconds($delay))
            ->onQueue('emails');

        \Log::info('Reservation update messages dispatched', [
            'post_id' => $this->post->id,
            'organizer_id' => $organizer->id,
            'recipients_count' => count($allReserved) + 1, // +1 for organizer
            'group_conversation_id' => $groupConversation->id
        ]);

        // Clear the message and show success
        $this->messageToReserved = '';
        $this->showReservationsModal = false;

        $this->notification()->success(
            __('Reservation update sent!'),
            __('All participants have been notified by email and chat message.')
        );
    }

    public function render()
    {
        return view('livewire.reserve-button');
    }
}
