<?php

// app/Http/Livewire/WireChat/TypingIndicator.php
namespace App\Http\Livewire\WireChat;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;
use Livewire\Component;

class TypingIndicator extends Component
{
    // Public properties
    public $conversationId;
    public $typingUsers = [];
    public $currentUserId;
    public $currentUserName;
    public $currentUserType;
    public $currentUserAvatar;
    public $showAvatars = true;
    public $maxDisplay = 3;

    protected $typingTimeout = 4;

    public function mount($conversationId, $showAvatars = true, $maxDisplay = 3)
    {
        $this->conversationId = $conversationId;
        $this->showAvatars = $showAvatars;
        $this->maxDisplay = $maxDisplay;
        $this->typingUsers = [];

        $user = auth()->user();
        if ($user) {
            $this->currentUserId = $user->id;
            $this->currentUserName = $user->name;
            $this->currentUserType = class_basename($user->getMorphClass());
            $this->currentUserAvatar = ($user->getMorphClass())::find($this->currentUserId)->profile_photo_path ?? null;
        }

        $this->loadTypingUsers();
    }

    /**
     * Get the cache key for this user's typing status
     */
    private function getCacheKey()
    {
        // Simplified cache key format without special characters
        return "wirechat_typing_{$this->conversationId}_{$this->currentUserType}_{$this->currentUserId}";
    }

    /**
     * Get the pattern for finding all typing users in this conversation
     */
    private function getCachePattern()
    {
        return "wirechat_typing_{$this->conversationId}_*";
    }

    /**
     * Start typing - called from JavaScript
     */
    public function startTyping()
    {
        if (!$this->currentUserId) {
            \Log::warning('TypingIndicator: No current user ID');
            return;
        }

        $cacheKey = $this->getCacheKey();

        $userData = [
            'user_id' => $this->currentUserId,
            'user_name' => $this->currentUserName,
            'user_type' => $this->currentUserType,
            'avatar' => $this->currentUserAvatar,
            'started_at' => now(),
            'conversation_id' => $this->conversationId,
        ];

        try {
            // Store with expiration
            Cache::put($cacheKey, $userData, now()->addSeconds($this->typingTimeout + 2));

            // Immediately load typing users to update the display
            $this->loadTypingUsers();
        } catch (\Exception $e) {
            \Log::error('TypingIndicator: Error starting typing', [
                'error' => $e->getMessage(),
                'cache_key' => $cacheKey
            ]);
        }
    }

    /**
     * Stop typing - called from JavaScript
     */
    public function stopTyping()
    {
        if (!$this->currentUserId) {
            return;
        }

        $cacheKey = $this->getCacheKey();

        try {
            Cache::forget($cacheKey);

            $this->loadTypingUsers();
        } catch (\Exception $e) {
            \Log::error('TypingIndicator: Error stopping typing', [
                'error' => $e->getMessage(),
                'cache_key' => $cacheKey
            ]);
        }
    }

    /**
     * Load typing users from cache
     */
    public function loadTypingUsers()
    {
        try {
            $typingUsers = [];

            // Get the correct Redis connection for cache
            $cacheRedisConnection = config('cache.stores.redis.connection', 'default');

            // From the exact debugging, the actual format is:
            // Redis key: timebankcc_dev_on_thinkpad_p53_database_timebankcc_dev_on_thinkpad_p53_cache:wirechat_typing_1_User_161
            // But we search with: timebankcc_dev_on_thinkpad_p53_cache:wirechat_typing_1_*
            // And need to extract: wirechat_typing_1_User_161

            $cachePrefix = config('cache.prefix', '');
            $databasePrefix = config('database.redis.options.prefix', '');
            $pattern = $this->getCachePattern();

            // Use the working search pattern (cache prefix only)
            $searchPattern = $cachePrefix . ':' . $pattern;

            // But the actual key prefix includes database prefix
            $actualKeyPrefix = $databasePrefix . $cachePrefix . ':';

            if (config('cache.default') === 'redis') {
                // Use the CACHE Redis connection (database 1)
                $connection = Redis::connection($cacheRedisConnection);
                $redisKeys = $connection->keys($searchPattern);

                foreach ($redisKeys as $redisKey) {
                    // Extract the Laravel cache key by removing the ACTUAL prefix (database + cache)
                    if (strpos($redisKey, $actualKeyPrefix) === 0) {
                        $laravelCacheKey = substr($redisKey, strlen($actualKeyPrefix));
                    } else {
                        // Fallback - the key format might be different
                        \Log::warning('TypingIndicator: Unexpected key format', [
                            'redis_key' => $redisKey,
                            'expected_prefix' => $actualKeyPrefix
                        ]);
                        continue;
                    }

                    // Use Laravel Cache to get the data (it handles serialization properly)
                    $userData = Cache::get($laravelCacheKey);

                    if ($userData && isset($userData['user_id']) && $userData['user_id'] != $this->currentUserId) {
                        if (isset($userData['started_at']) && $userData['started_at']->diffInSeconds(now()) <= $this->typingTimeout) {
                            $typingUsers[] = $userData;
                            \Log::info('TypingIndicator: Added typing user', [
                                'user_id' => $userData['user_id'],
                                'user_name' => $userData['user_name']
                            ]);
                        } else {
                            // Clean up expired entries
                            Cache::forget($laravelCacheKey);
                        }
                    } elseif ($userData && $userData['user_id'] == $this->currentUserId) {
                        \Log::info('TypingIndicator: Ignoring current user\'s typing', [
                            'current_user_id' => $this->currentUserId
                        ]);
                    }
                }
            } else {
                // Fallback for non-Redis cache drivers
                $registryKey = "typing_registry_{$this->conversationId}";
                $registry = Cache::get($registryKey, []);

                foreach ($registry as $key) {
                    $userData = Cache::get($key);
                    if ($userData && isset($userData['user_id']) && $userData['user_id'] != $this->currentUserId) {
                        if (isset($userData['started_at']) && $userData['started_at']->diffInSeconds(now()) <= $this->typingTimeout) {
                            $typingUsers[] = $userData;
                        }
                    }
                }
            }

            $this->typingUsers = collect($typingUsers)->take($this->maxDisplay)->toArray();

        } catch (\Exception $e) {
            $this->typingUsers = [];
            \Log::error('TypingIndicator: Error loading typing users', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
        }
    }

    /**
     * Get typing text for display
     */
    public function getTypingText()
    {
        $count = is_array($this->typingUsers) ? count($this->typingUsers) : 0;

        if ($count === 0) {
            return '';
        } elseif ($count === 1) {
            return ($this->typingUsers[0]['user_name'] ?? 'Someone') . ' is typing...';
        } elseif ($count === 2) {
            $name1 = $this->typingUsers[0]['user_name'] ?? 'Someone';
            $name2 = $this->typingUsers[1]['user_name'] ?? 'Someone';
            return $name1 . ' and ' . $name2 . ' are typing...';
        } else {
            $name1 = $this->typingUsers[0]['user_name'] ?? 'Someone';
            return $name1 . ' and ' . ($count - 1) . ' others are typing...';
        }
    }

    /**
     * Manual refresh method
     */
    public function refresh()
    {
        $this->loadTypingUsers();
    }

    /**
     * Enhanced debug method
     */
    public function debug()
    {
        $cacheKey = $this->getCacheKey();
        $pattern = $this->getCachePattern();

        // Get Redis connection info
        $cacheRedisConnection = config('cache.stores.redis.connection', 'default');
        $cachePrefix = config('cache.prefix', '');
        $databasePrefix = config('database.redis.options.prefix', '');

        // Build the full pattern accounting for both prefixes
        $fullPattern = '';
        if ($databasePrefix) {
            $fullPattern .= $databasePrefix;
        }
        if ($cachePrefix) {
            $fullPattern .= $cachePrefix . ':';
        }
        $fullPattern .= $pattern;

        $redisKeys = [];
        $redisData = [];

        if (config('cache.default') === 'redis') {
            try {
                $connection = Redis::connection($cacheRedisConnection);

                // Check for typing keys with the full pattern
                $allTypingKeys = $connection->keys($databasePrefix ? $databasePrefix . $cachePrefix . ':*typing*' : $cachePrefix . ':*typing*');
                $patternKeys = $connection->keys($fullPattern);

                $redisKeys = [
                    'all_typing_keys' => $allTypingKeys,
                    'pattern_keys' => $patternKeys,
                    'current_user_key' => $cacheKey,
                    'full_pattern_searched' => $fullPattern,
                    'cache_redis_connection' => $cacheRedisConnection
                ];

                foreach ($patternKeys as $key) {
                    // Extract the Laravel cache key by removing both prefixes
                    $cleanKey = $key;
                    if ($databasePrefix && strpos($cleanKey, $databasePrefix) === 0) {
                        $cleanKey = substr($cleanKey, strlen($databasePrefix));
                    }
                    if ($cachePrefix && strpos($cleanKey, $cachePrefix . ':') === 0) {
                        $cleanKey = substr($cleanKey, strlen($cachePrefix . ':'));
                    }

                    $data = Cache::get($cleanKey);
                    if ($data) {
                        $redisData[] = [
                            'full_redis_key' => $key,
                            'clean_cache_key' => $cleanKey,
                            'data' => $data
                        ];
                    }
                }
            } catch (\Exception $e) {
                \Log::error('TypingIndicator: Redis debug error', ['error' => $e->getMessage()]);
            }
        }

        $debugInfo = [
            'conversationId' => $this->conversationId,
            'typingUsers' => $this->typingUsers,
            'typingUsersCount' => is_array($this->typingUsers) ? count($this->typingUsers) : 'not-array',
            'currentUserId' => $this->currentUserId,
            'currentUserName' => $this->currentUserName,
            'currentUserType' => $this->currentUserType,
            'showAvatars' => $this->showAvatars,
            'cacheDriver' => config('cache.default'),
            'cacheKey' => $cacheKey,
            'cachePattern' => $pattern,
            'cachePrefix' => $cachePrefix,
            'databasePrefix' => $databasePrefix,
            'fullPattern' => $fullPattern,
            'cacheRedisConnection' => $cacheRedisConnection,
            'redisKeys' => $redisKeys,
            'redisData' => $redisData,
            'typingTimeout' => $this->typingTimeout,
        ];

        \Log::info('TypingIndicator: Debug info', $debugInfo);

        return $debugInfo;
    }

    public function render()
    {
        return view('livewire.wire-chat.typing-indicator');
    }
}
