<?php

namespace App\Http\Livewire\Search;

use App\Models\Bank;
use App\Models\Organization;
use App\Models\Post;
use App\Models\User;
use App\Traits\LocationTrait;
use App\Traits\ProfileTrait;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
use Livewire\WithPagination;

class Show extends Component
{
    use WithPagination;
    use ProfileTrait;
    use LocationTrait;

    public $searchTerm = '';
    public $resultRefs = [];
    public $total = 0;
    public $perPage = 15;
    
    protected $queryString = [
        'perPage' => ['except' => 15],
        'searchTerm' => ['except' => '']
    ];

    public function mount($resultRefs = [], $searchTerm = '', $total = 0)
    {
        $this->resultRefs = $resultRefs;
        $this->searchTerm = $searchTerm;
        $this->total = $total;
        
    }

    public function showProfile($id, $model)
    {
        $this->extendCachedResults();
        $modelName = __(strtolower($model));
        $this->redirectRoute('profile.show_by_type_and_id', ['type' => $modelName, 'id' => $id]);
    }


    public function showPost($id)
    {
        $this->extendCachedResults();
        $this->redirectRoute('post.show', ['id' => $id]);
    }

    public function showCall($id)
    {
        $this->extendCachedResults();
        $this->redirectRoute('call.show', ['id' => $id]);
    }


    private function extendCachedResults()
    {
        $key = 'main_search_bar_results_' . Auth::guard('web')->id();
        $cacheData = cache()->get($key);

        if ($cacheData) {
            // Re-store with extended TTL (e.g., reset TTL and add 5 more minutes)
            cache()->put($key, $cacheData, now()->addMinutes(timebank_config('main_search_bar.cache_results', 5)));
        }
    }

    public function updatedPage()
    {
        $this->dispatch('scroll-to-top');
    }



    public function render()
    {
        // Group model IDs by type for efficient eager loading
        $modelsByType = collect($this->resultRefs)->groupBy('model');

        // Eager load models with their reaction data
        $loadedModels = [];
        foreach ($modelsByType as $modelClass => $refs) {
            $ids = collect($refs)->pluck('id')->toArray();

            if ($modelClass === \App\Models\Call::class) {
                $callQuery = $modelClass::with([
                    'callable.locations.city.translations',
                    'callable.locations.division.translations',
                    'callable.locations.country.translations',
                    'translations' => function ($query) {
                        $query->where('locale', App::getLocale());
                    },
                    'tag.contexts.category.translations',
                    'tag.contexts.category.ancestors.translations',
                    'location.city.translations',
                    'location.country.translations',
                    'loveReactant.reactionCounters',
                ])->whereIn('id', $ids);
                if (!\Illuminate\Support\Facades\Auth::check()) {
                    $callQuery->where('is_public', true);
                }
                $models = $callQuery->get()->keyBy('id');
            } elseif ($modelClass === \App\Models\Post::class) {
                // Posts don't need reaction loading for now
                $models = $modelClass::with([
                    'postable' => function ($query) {
                        $query->select(['id', 'name']);
                    },
                    'category' => function ($query) {
                        $query->with('translations');
                    },
                    'translations' => function ($query) {
                        $query
                            ->where('locale', App::getLocale())
                            ->whereDate('from', '<=', now())
                            ->where(function ($query) {
                                $query->whereDate('till', '>', now())->orWhereNull('till');
                            });
                    },
                    'meeting.location.district.translations',
                    'meeting.location.city.translations',
                    'meeting.location.country.translations',
                ])->whereIn('id', $ids)->get()->keyBy('id');
            } else {
                // Profile models (User, Organization, Bank) with reaction data
                $models = $modelClass::with([
                    'loveReactant.reactionCounters'
                ])->whereIn('id', $ids)->get()->keyBy('id');
            }

            $loadedModels[$modelClass] = $models;
        }

        // Map refs to actual models and result arrays
        $results = collect($this->resultRefs)->map(function ($ref) use ($loadedModels) {
            $modelClass = $ref['model'];
            $model = $loadedModels[$modelClass][$ref['id']] ?? null;

            if (!$model) {
                return null;
            }

            $highlight = $ref['highlight'] ?? [];
            $score = $ref['score'] ?? null;

            // POST & CALL MODELS
            switch ($modelClass) {
                case \App\Models\Call::class:
                    $translation = $model->translations->first();
                    $tag = $model->tag;
                    $tagContext = $tag?->contexts->first();
                    $tagCategory = $tagContext?->category;
                    $tagColor = $tagCategory?->relatedColor ?? 'gray';
                    $tagName  = $tag?->translation?->name ?? $tag?->name;
                    $locationStr = null;
                    if ($model->location) {
                        $loc   = $model->location;
                        $locParts = [];
                        if ($loc->city) {
                            $cityName = optional($loc->city->translations->first())->name;
                            if ($cityName) $locParts[] = $cityName;
                        }
                        if ($loc->country) {
                            if ($loc->country->code === 'XX') {
                                $locParts[] = __('Location not specified');
                            } elseif ($loc->country->code) {
                                $locParts[] = strtoupper($loc->country->code);
                            }
                        }
                        $locationStr = $locParts ? implode(', ', $locParts) : null;
                    }

                    // Build category hierarchy: ancestors (root first) + self
                    $tagCategories = [];
                    if ($tagCategory) {
                        $ancestors = $tagCategory->ancestorsAndSelf()->get()->reverse();
                        $locale = App::getLocale();
                        foreach ($ancestors as $cat) {
                            $catName = $cat->translations->firstWhere('locale', $locale)?->name
                                ?? $cat->translations->first()?->name
                                ?? '';
                            if ($catName) {
                                $tagCategories[] = [
                                    'name'  => $catName,
                                    'color' => $cat->relatedColor ?? 'gray',
                                ];
                            }
                        }
                    }

                    return [
                        'id'            => $model->id,
                        'model'         => $modelClass,
                        'category_id'   => null,
                        'category'      => trans_with_platform('@PLATFORM_NAME@ call'),
                        'title'         => $tagName ?? '',
                        'excerpt'       => $translation?->content ?? '',
                        'photo'         => $model->callable?->profile_photo_url ?? '',
                        'location'      => $locationStr,
                        'location_short' => $city ?? '',
                        'tag_name'      => $tagName,
                        'tag_color'     => $tagColor,
                        'tag_categories' => $tagCategories,
                        'callable_name'     => $model->callable?->name ?? '',
                        'callable_location' => \App\Http\Livewire\Calls\ProfileCalls::buildCallableLocation($model->callable),
                        'till'               => $model->till,
                        'expiry_badge_text'  => \App\Http\Livewire\Calls\ProfileCalls::buildExpiryBadgeText($model->till),
                        'meeting_venue' => '',
                        'meeting_address' => '',
                        'meeting_city'  => '',
                        'meeting_location' => '',
                        'meeting_date_from' => '',
                        'meeting_date_till' => '',
                        'status'        => '',
                        'highlight'     => $highlight,
                        'score'         => $score,
                        'like_count'    => $model->loveReactant?->reactionCounters->firstWhere('reaction_type_id', 3)?->count ?? 0,
                        'bookmark_count' => $model->loveReactant?->reactionCounters->firstWhere('reaction_type_id', 2)?->count ?? 0,
                        'star_count'    => 0,
                    ];

                case \App\Models\Post::class:
                    $categoryId = optional($model->category)->id;
                    $categoryName = optional($model->category->translations->where('locale', app()->getLocale())->first())->name;
                    $photoUrl = $model->getFirstMediaUrl('posts', 'hero');

                    return [
                        'id' => $model->id,
                        'model' => $modelClass,
                        'category_id' => $categoryId,
                        'category' => $categoryName,
                        'title' => $model->translations->first()->title,
                        'excerpt' => $model->translations->first()->excerpt,
                        'photo' => $photoUrl,
                        'location' => '',
                        'location_short' => '',
                        'meeting_venue' => $model->meeting->venue ?? '',
                        'meeting_address' => $model->meeting->address ?? '',
                        'meeting_city' => $model->meeting->location->city->translations ?? '',
                        'meeting_location' => $model->meeting ? $model->meeting->getLocationFirst() : '',
                        'meeting_date_from' => $model->meeting->from ?? '',
                        'meeting_date_till' => $model->meeting->till ?? '',
                        'status' => '',
                        'highlight' => $highlight,
                        'score' => $score,
                        'bookmark_count' => 0,
                        'star_count' => 0,
                        'like_count' => 0,
                    ];

                    // PROFILE MODELS
                case \App\Models\User::class:
                case \App\Models\Organization::class:
                case \App\Models\Bank::class:
                    // Extract reaction counts using Laravel-Love's built-in methods
                    $bookmarkCount = 0;
                    $starCount = 0;
                    $likeCount = 0;

                    if ($model->loveReactant) {
                        // Get reaction types first
                        $bookmarkType = \Cog\Laravel\Love\ReactionType\Models\ReactionType::fromName('bookmark');
                        $starType = \Cog\Laravel\Love\ReactionType\Models\ReactionType::fromName('star');
                        $likeType = \Cog\Laravel\Love\ReactionType\Models\ReactionType::fromName('like');

                        // Get counts using the ReactionType objects and extract the count value
                        if ($bookmarkType) {
                            $bookmarkCounter = $model->loveReactant->getReactionCounterOfType($bookmarkType);
                            $bookmarkCount = $bookmarkCounter->getCount();
                        }
                        if ($starType) {
                            $starCounter = $model->loveReactant->getReactionCounterOfType($starType);
                            $starCount = $starCounter->getCount();
                        }
                        if ($likeType) {
                            $likeCounter = $model->loveReactant->getReactionCounterOfType($likeType);
                            $likeCount = $likeCounter->getCount();
                        }
                    }

                    return [
                        'id' => $model->id,
                        'model' => $modelClass,
                        'name' => $model->name,
                        'full_name' => $model->full_name,
                        'about_short' => $model->about_short,
                        'about' => $model->about,
                        'motivation' => $model->motivation,
                        'photo' => $model->profile_photo_path,
                        'location' => $model->getLocationFirst(false)['name'] ?? '',
                        'location_short' => $model->getLocationFirst(false)['name_short'] ?? '',
                        'skills' => $this->getSkills($model) ?? '',
                        'cyclos_skills' => $model->cyclos_skills ?? '',
                        'deleted_at' => $model->deleted_at,
                        'status' => '',
                        'highlight' => $highlight,
                        'score' => $score,
                        'bookmark_count' => $bookmarkCount,
                        'star_count' => $starCount,
                        'like_count' => $likeCount,
                    ];

                default:
                    return null;
            }
        })->filter()->values();

        // Use Livewire's built-in pagination
        $currentPage = $this->getPage();
        $results = $results->slice(($currentPage - 1) * $this->perPage, $this->perPage)->values();
        
        $paginator = new \Illuminate\Pagination\LengthAwarePaginator(
            $results,
            collect($this->resultRefs)->count(),
            $this->perPage,
            $currentPage,
            [
                'path' => request()->url(),
                'pageName' => 'page'
            ]
        );
        
        $paginator->withQueryString();

        return view('livewire.search.show', ['results' => $paginator]);
    }
}
