<?php

namespace App\Http\Livewire;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Livewire\Component;

class SwitchProfileUnreadIndicator extends Component
{
    public $hasAnyUnread = false;

    public function mount()
    {
        $this->loadUnreadStatus();

        // Dispatch browser event to notify JavaScript
        $this->dispatch('switch-profile-unread-updated', hasUnread: $this->hasAnyUnread);
    }

    private function loadUnreadStatus()
    {
        $webUser = Auth::guard('web')->user();
        if (!$webUser) {
            return;
        }

        // Get user's profiles using same logic as SwitchProfile
        $userWithRelations = \App\Models\User::with([
            'organizations',
            'banksManaged',
            'admins'
        ])->find($webUser->id);

        if (!$userWithRelations) {
            return;
        }

        // Filter out removed (soft-deleted) items
        $organizations = $userWithRelations->organizations->filter(
            fn ($organizations) => $organizations->deleted_at === null || $organizations->deleted_at > now()
        );
        $banks = $userWithRelations->banksManaged->filter(
            fn ($bank) => $bank->deleted_at === null || $bank->deleted_at > now()
        );
        $admins = $userWithRelations->admins->filter(
            fn ($admin) => $admin->deleted_at === null || $admin->deleted_at > now()
        );

        // Merge profiles collections
        $profiles = $organizations
            ->concat($banks)
            ->concat($admins);

        // Collect all profile IDs
        $profileIds = [
            'user' => [$webUser->id],
            'admin' => [],
            'bank' => [],
            'organization' => [],
        ];

        foreach ($profiles as $profile) {
            if ($profile instanceof \App\Models\Organization) {
                $profileIds['organization'][] = $profile->id;
            } elseif ($profile instanceof \App\Models\Bank) {
                $profileIds['bank'][] = $profile->id;
            } elseif ($profile instanceof \App\Models\Admin) {
                $profileIds['admin'][] = $profile->id;
            }
        }

        // Get active profile info to exclude it from unread check
        $activeProfileType = session('activeProfileType');
        $activeProfileId = session('activeProfileId');

        // Check for unread messages
        $profilesWithUnread = $this->checkUnreadMessages($profileIds);

        // Check if ANY profile has unread (EXCLUDING the currently active profile)
        // Get the active profile type key
        $activeTypeKey = null;
        if ($activeProfileType) {
            $activeTypeKey = match($activeProfileType) {
                'App\\Models\\User', 'App\Models\User' => 'user',
                'App\\Models\\Admin', 'App\Models\Admin' => 'admin',
                'App\\Models\\Bank', 'App\Models\Bank' => 'bank',
                'App\\Models\\Organization', 'App\Models\Organization' => 'organization',
                default => null
            };
        }

        // Check user profile (only if not active)
        if ($activeTypeKey !== 'user') {
            $this->hasAnyUnread = $profilesWithUnread['user'] ?? false;
        }

        // Check other profile types (excluding active)
        if (!$this->hasAnyUnread) {
            foreach (['admin', 'bank', 'organization'] as $type) {
                if (!empty($profilesWithUnread[$type])) {
                    foreach ($profilesWithUnread[$type] as $profileId => $hasUnread) {
                        // Skip if this is the active profile
                        if ($activeTypeKey === $type && $activeProfileId == $profileId) {
                            continue;
                        }
                        if ($hasUnread) {
                            $this->hasAnyUnread = true;
                            break 2;
                        }
                    }
                }
            }
        }
    }

    private function checkUnreadMessages(array $profileIds): array
    {
        $result = [
            'user' => false,
            'admin' => [],
            'bank' => [],
            'organization' => [],
        ];

        // Collect all profile type/id pairs
        $profilePairs = [];
        foreach ($profileIds as $type => $ids) {
            foreach ($ids as $id) {
                $modelClass = $this->getModelClass($type);
                $profilePairs[] = ['type' => $modelClass, 'id' => $id];
            }
        }

        if (empty($profilePairs)) {
            return $result;
        }

        // Use parameter binding with IN clause for better escaping
        $typeIds = collect($profilePairs)->groupBy('type')->map(function ($items) {
            return $items->pluck('id')->toArray();
        })->toArray();

        // Check each type separately and combine results
        foreach ($typeIds as $modelClass => $ids) {
            $unreadForType = DB::table('wirechat_participants as p')
                ->select('p.participantable_type', 'p.participantable_id')
                ->join('wirechat_conversations as c', 'p.conversation_id', '=', 'c.id')
                ->where('p.participantable_type', '=', $modelClass)
                ->whereIn('p.participantable_id', $ids)
                ->whereNull('p.deleted_at')
                ->whereExists(function ($query) {
                    $query->select(DB::raw(1))
                        ->from('wirechat_messages as m')
                        ->whereColumn('m.conversation_id', 'p.conversation_id')
                        ->whereNull('m.deleted_at')
                        ->where(function ($q) {
                            $q->whereNull('p.conversation_read_at')
                              ->orWhereColumn('m.created_at', '>', 'p.conversation_read_at');
                        })
                        ->where(function ($q) {
                            $q->where('m.sendable_id', '!=', DB::raw('p.participantable_id'))
                              ->orWhere('m.sendable_type', '!=', DB::raw('p.participantable_type'));
                        });
                })
                ->get();

            foreach ($unreadForType as $row) {
                $type = $this->getTypeFromModelClass($row->participantable_type);
                $id = $row->participantable_id;

                if ($type === 'user') {
                    $result['user'] = true;
                } else {
                    $result[$type][$id] = true;
                }
            }
        }

        return $result;
    }

    private function getModelClass(string $type): string
    {
        return match($type) {
            'user' => 'App\Models\User',
            'admin' => 'App\Models\Admin',
            'bank' => 'App\Models\Bank',
            'organization' => 'App\Models\Organization',
        };
    }

    private function getTypeFromModelClass(string $class): string
    {
        return match($class) {
            'App\\Models\\User', 'App\Models\User' => 'user',
            'App\\Models\\Admin', 'App\Models\Admin' => 'admin',
            'App\\Models\\Bank', 'App\Models\Bank' => 'bank',
            'App\\Models\\Organization', 'App\Models\Organization' => 'organization',
            default => 'unknown'
        };
    }

    public function render()
    {
        return view('livewire.switch-profile-unread-indicator');
    }
}
