<?php

namespace App\Http\Livewire;

use App\Services\PresenceService;
use Cog\Laravel\Love\ReactionType\Models\ReactionType;
use Cog\Laravel\Love\Reaction\Models\Reaction;
use Livewire\Attributes\On;
use Livewire\Component;

class OnlineReactedProfiles extends Component
{
    // Configuration properties
    public $reactionTypes = []; // ['Bookmark', 'Star', 'Like'] or single 'Bookmark'
    public $guards = ['web']; // Which guards to check for online users
    public $authGuard; // Current user's guard
    public $showCount = true;
    public $showAvatars = true;
    public $maxDisplay = 20;
    public $headerText; // Header text for the component
    public $refreshInterval = 10;
    public $groupByModel = true; // Group results by model type
    public $lastSeen = false; // Show last seen time
    public $modelLabels = [
        'App\Models\User' => 'Persons',
        'App\Models\Organization' => 'Organizations',
        'App\Models\Bank' => 'Banks',
        'App\Models\Admin' => 'Admins',
    ];

    // Data properties
    public $onlineReactedProfiles = [];
    public $totalCount = 0;
    public $countByType = [];

    // Logout modal properties
    public $showLogoutModal = false;
    public $selectedProfileId = null;
    public $selectedProfileType = null;
    public $selectedProfileName = null;

    public function mount(
        $reactionTypes = null,
        $guards = null,
        $showCount = true,
        $showAvatars = true,
        $maxDisplay = 20,
        $header = true,
        $headerText = null,
        $groupByModel = false,
        $lastSeen = false
    ) {
        // Setup reaction types
        if ($reactionTypes !== null) {
            if (is_string($reactionTypes)) {
                $this->reactionTypes = array_map('trim', explode(',', $reactionTypes));
            } else {
                $this->reactionTypes = is_array($reactionTypes) ? $reactionTypes : [$reactionTypes];
            }
        } else {
            // Keep as null to show all online users without filtering
            $this->reactionTypes = null;
        }

        // Setup guards to check
        if ($guards) {
            $this->guards = is_array($guards) ? $guards : [$guards];
        } else {
            // Check all guards by default
            $this->guards = ['web', 'organization', 'bank'];
        }

        // Determine current auth guard
        $this->authGuard = session('active_guard') ?? 'web';

        // Set display options
        $this->showCount = $showCount;
        $this->showAvatars = $showAvatars;
        $this->maxDisplay = $maxDisplay;
        $this->groupByModel = $groupByModel;
        $this->lastSeen = $lastSeen;

        // Load initial data
        $this->loadOnlineReactedProfiles();


        // Set header text if required
        if ($header) {
            if ($headerText) {
                $this->headerText = $headerText;
            } else {
                $this->headerText = $this->getHeaderText($this->reactionTypes);
            }
        } else {
            $this->headerText = null;
        }
    }

    /**
     * Get the header text based on reaction types.
     * If no reaction types, return a default message.
     */
    public function getHeaderText($reactionTypes)
    {
        if ($this->reactionTypes === null) {
            // Show all online users
            return trans_choice('messages.profiles_online', $this->totalCount, ['count' => $this->totalCount]);
        } elseif (!empty($reactionTypes)) {
            if (count($reactionTypes) === 1) {
                return trans_choice('messages.' . strtolower($reactionTypes[0]) . '_contacts_online', $this->totalCount, ['count' => $this->totalCount]);
            } elseif (count($reactionTypes) > 1) {
                return trans_choice('messages.reactions_contacts_online', $this->totalCount, ['count' => $this->totalCount]);
            }
        }
        return 'Error: no reaction types found.';
    }



    public function loadOnlineReactedProfiles()
    {
        try {
            // Get authenticated user/profile
            $authUser = auth($this->authGuard)->user();

            if (!$authUser) {
                $this->onlineReactedProfiles = [];
                $this->totalCount = 0;
                return;
            }

            // Only require viaLoveReacter if filtering by reactions
            if ($this->reactionTypes !== null && !method_exists($authUser, 'viaLoveReacter')) {
                $this->onlineReactedProfiles = [];
                $this->totalCount = 0;
                return;
            }

            // Collect all online users from specified guards
            $allOnlineProfiles = collect();

            foreach ($this->guards as $guard) {
                try {
                    $presenceService = app(PresenceService::class);
                    $onlineUsers = $presenceService->getOnlineUsers($guard);

                    foreach ($onlineUsers as $userData) {
                        // Get the actual model instance
                        $model = $this->getModelFromUserData($userData, $guard);

                        // If filtering by reactions, check for love reactant trait
                        // If not filtering (reactionTypes is null), just check if model exists
                        if ($model && ($this->reactionTypes === null || method_exists($model, 'viaLoveReactant'))) {
                            $profileData = $this->buildProfileData($model, $userData, $guard);

                            if ($profileData) {
                                $allOnlineProfiles->push($profileData);
                            }
                        }
                    }
                } catch (\Exception $e) {
                    \Log::error('Error loading online profiles for guard ' . $guard . ': ' . $e->getMessage());
                }
            }

            // Filter profiles based on whether we're filtering by reactions or not
            if ($this->reactionTypes === null) {
                // Show all online profiles without reaction filtering
                $reactedProfiles = $allOnlineProfiles;
            } else {
                // Filter profiles that have been reacted to
                $reactedProfiles = $allOnlineProfiles->filter(function ($profile) {
                    return $this->hasAuthUserReacted($profile['model']);
                });
            }

            // Apply display limit
            $limitedProfiles = $reactedProfiles->take($this->maxDisplay);

            // Group by model if requested
            if ($this->groupByModel) {
                $this->onlineReactedProfiles = $limitedProfiles
                    ->groupBy('model_type')
                    ->toArray();
            } else {
                $this->onlineReactedProfiles = $limitedProfiles->values()->toArray();
            }

            // Update counts
            $this->totalCount = $reactedProfiles->count();
            $this->countByType = $reactedProfiles->groupBy('model_type')->map->count()->toArray();

            // Dispatch event for other components
            $this->dispatch('online-reacted-profiles-updated', [
                'count' => $this->totalCount,
                'profiles' => $this->onlineReactedProfiles
            ]);
        } catch (\Exception $e) {
            \Log::error('Error loading online reacted profiles: ' . $e->getMessage());
            $this->onlineReactedProfiles = [];
            $this->totalCount = 0;
        }
    }

    protected function getModelFromUserData($userData, $guard)
    {
        try {
            // Get the model class for this guard
            $modelClass = $this->getModelClassForGuard($guard);

            if (!$modelClass) {
                return null;
            }

            // Handle both array and object formats
            $userId = is_array($userData) ? ($userData['id'] ?? null) : ($userData->id ?? null);

            if (!$userId) {
                return null;
            }

            return $modelClass::find($userId);
        } catch (\Exception $e) {
            \Log::error('Error getting model from user data: ' . $e->getMessage());
            return null;
        }
    }

    protected function getModelClassForGuard($guard)
    {
        // Map guards to model classes
        $guardModelMap = [
            'web' => \App\Models\User::class,
            'organization' => \App\Models\Organization::class,
            'bank' => \App\Models\Bank::class,
            'admin' => \App\Models\Admin::class,
        ];

        return $guardModelMap[$guard] ?? null;
    }

    protected function buildProfileData($model, $userData, $guard)
    {
        try {
            // Get reactions for this profile
            $reactions = $this->getReactionsForProfile($model);
            // Build profile data array
            return [
                'id' => $model->id,
                'model' => $model,
                'model_type' => get_class($model),
                'model_label' => $this->modelLabels[get_class($model)] ?? class_basename($model),
                'guard' => $guard,
                'name' => $model->name ?? 'Unknown',
                'location' => $model->getLocationFirst()['name_short'] ?? '',
                'avatar' => $model->profile_photo_path ?? null,
                'last_seen' => is_array($userData) ?
                    ($userData['last_seen'] ?? now()) : ($userData->last_seen ?? now()),
                'reactions' => $reactions,
                'profile_url' => route('profile.show_by_type_and_id', ['type' => __(strtolower(class_basename($model))), 'id' => $model->id]),
                'is_online' => true,
            ];
        } catch (\Exception $e) {
            \Log::error('Error building profile data: ' . $e->getMessage());
            return null;
        }
    }

    protected function hasAuthUserReacted($model)
    {
        try {
            // If no reaction types specified, return true (show all)
            if ($this->reactionTypes === null) {
                return true;
            }

            if (!method_exists($model, 'viaLoveReactant')) {
                return false;
            }

            $reactantFacade = $model->viaLoveReactant();

            // Get the authenticated user directly
            $authUser = auth($this->authGuard)->user();
            if (!$authUser) {
                return false;
            }

            // Check if empty array (different from null)
            if (is_array($this->reactionTypes) && empty($this->reactionTypes)) {
                return false;
            }

            foreach ($this->reactionTypes as $reactionType) {
                if ($reactantFacade->isReactedBy($authUser, $reactionType)) {
                    return true;
                }
            }

            return false;
        } catch (\Exception $e) {
            \Log::error('Error checking reactions: ' . $e->getMessage());
            return false;
        }
    }


    protected function getReactionsForProfile($model)
    {
        try {
            if (!method_exists($model, 'viaLoveReactant')) {
                return [];
            }

            $reactantFacade = $model->viaLoveReactant();
            $reactions = [];

            // Get the authenticated user directly
            $authUser = auth($this->authGuard)->user();
            if (!$authUser) {
                return [];
            }

            if ($this->reactionTypes !== null) {
                foreach ($this->reactionTypes as $reactionType) {
                    if ($reactantFacade->isReactedBy($authUser, $reactionType)) {
                        $reactions[] = [
                            'type' => $reactionType,
                        ];
                    }
                }
            }

            return $reactions;
        } catch (\Exception $e) {
            \Log::error('Error getting reactions for profile: ' . $e->getMessage());
            return [];
        }
    }


    public function toggleReaction($profileId, $modelType, $reactionType)
    {
        try {
            $authUser = auth($this->authGuard)->user();
            if (!$authUser) {
                return;
            }

            $model = $modelType::find($profileId);
            if (!$model) {
                return;
            }

            $reacterFacade = $authUser->viaLoveReacter();
            $reactantFacade = $model->viaLoveReactant();

            if ($reactantFacade->isReactedBy($authUser, $reactionType)) {
                $reacterFacade->unreactTo($model, $reactionType);
            } else {
                $reacterFacade->reactTo($model, $reactionType);
            }

            $this->loadOnlineReactedProfiles();
        } catch (\Exception $e) {
            \Log::error('Error toggling reaction: ' . $e->getMessage());
        }
    }

    #[On('presence-updated')]
    public function refreshProfiles()
    {
        $this->loadOnlineReactedProfiles();
    }

    #[On('user-activity')]
    public function onUserActivity()
    {
        $this->loadOnlineReactedProfiles();
    }

    public function isCurrentUserProfile($profileId, $modelType)
    {
        // Get the active profile using getActiveProfile() helper
        $activeProfile = getActiveProfile();

        if (!$activeProfile) {
            return false;
        }

        // Check if this is the current active profile (admin or any other type)
        if (get_class($activeProfile) === $modelType || get_class($activeProfile) === '\\' . $modelType) {
            if ($activeProfile->id === $profileId) {
                return true;
            }
        }

        // If the active profile is an Admin, check for related users
        if (get_class($activeProfile) === \App\Models\Admin::class) {
            if (method_exists($activeProfile, 'users')) {
                $relatedUsers = $activeProfile->users()->pluck('users.id')->toArray();

                if ($modelType === 'App\Models\User' || $modelType === \App\Models\User::class) {
                    return in_array($profileId, $relatedUsers);
                }
            }
        }

        return false;
    }

    public function openLogoutModal($profileId, $modelType)
    {
        // Verify admin access
        if (getActiveProfileType() !== 'Admin') {
            $this->dispatch('notify', [
                'type' => 'error',
                'message' => 'Unauthorized action. Only administrators can log out users.'
            ]);
            return;
        }

        // Prevent logging out current admin or their related profiles
        if ($this->isCurrentUserProfile($profileId, $modelType)) {
            $this->dispatch('notify', [
                'type' => 'error',
                'message' => 'You cannot log out your own profile or related user accounts.'
            ]);
            return;
        }

        $this->selectedProfileId = $profileId;
        $this->selectedProfileType = $modelType;

        // Get profile name for display
        try {
            $model = $modelType::find($profileId);
            $this->selectedProfileName = $model ? $model->name : null;
        } catch (\Exception $e) {
            $this->selectedProfileName = null;
        }

        $this->showLogoutModal = true;
    }

    public function closeLogoutModal()
    {
        $this->showLogoutModal = false;
        $this->selectedProfileId = null;
        $this->selectedProfileType = null;
        $this->selectedProfileName = null;
    }

    public function logoutUser()
    {
        // Verify admin access
        if (getActiveProfileType() !== 'Admin') {
            $this->dispatch('notify', [
                'type' => 'error',
                'message' => 'Unauthorized action. Only administrators can log out users.'
            ]);
            $this->closeLogoutModal();
            return;
        }

        try {
            if (!$this->selectedProfileId || !$this->selectedProfileType) {
                throw new \Exception('Invalid profile data');
            }

            $model = $this->selectedProfileType::find($this->selectedProfileId);

            if (!$model) {
                throw new \Exception('User not found');
            }

            // Get the guard for this model type
            $guard = $this->getGuardForModelType($this->selectedProfileType);

            if (!$guard) {
                throw new \Exception('Invalid guard');
            }

            // Broadcast logout event via websocket - this will force the user's browser to logout
            broadcast(new \App\Events\UserForcedLogout($this->selectedProfileId, $guard));

            // Delete all sessions for this user from the database
            \DB::connection(config('session.connection'))
                ->table(config('session.table', 'sessions'))
                ->where('user_id', $this->selectedProfileId)
                ->delete();

            // Clear any cached authentication data
            \Cache::forget('auth_' . $guard . '_' . $this->selectedProfileId);

            // Clear presence cache
            \Cache::forget("presence_{$guard}_{$this->selectedProfileId}");

            // Clear online users cache to force refresh
            \Cache::forget("online_users_{$guard}_" . \App\Services\PresenceService::ONLINE_THRESHOLD_MINUTES);

            // Set user offline in presence service
            $presenceService = app(\App\Services\PresenceService::class);
            $presenceService->setUserOffline($model, $guard);

            $this->dispatch('notify', [
                'type' => 'success',
                'message' => __('User has been logged out successfully.')
            ]);

            // Refresh the online profiles list
            $this->loadOnlineReactedProfiles();

        } catch (\Exception $e) {
            \Log::error('Error logging out user: ' . $e->getMessage());
            $this->dispatch('notify', [
                'type' => 'error',
                'message' => __('Failed to log out user. Please try again.')
            ]);
        }

        $this->closeLogoutModal();
    }

    protected function getGuardForModelType($modelType)
    {
        // Map model types to guards
        $modelGuardMap = [
            \App\Models\User::class => 'web',
            'App\Models\User' => 'web',
            \App\Models\Organization::class => 'organization',
            'App\Models\Organization' => 'organization',
            \App\Models\Bank::class => 'bank',
            'App\Models\Bank' => 'bank',
            \App\Models\Admin::class => 'admin',
            'App\Models\Admin' => 'admin',
        ];

        return $modelGuardMap[$modelType] ?? null;
    }

    public function render()
    {
        return view('livewire.online-reacted-profiles');
    }
}
