<?php

namespace App\Services\Messaging;

use App\Models\User;
use Illuminate\Cache\Repository;
use Illuminate\Support\Facades\Cache;

class MessagingPresenceService
{
    public function touch(User|int $user, ?int $conversationId = null): void
    {
        $userId = $user instanceof User ? (int) $user->id : (int) $user;
        $store = $this->store();
        $onlineKey = $this->onlineKey($userId);
        $existing = $store->get($onlineKey, []);
        $previousConversationId = (int) ($existing['conversation_id'] ?? 0) ?: null;
        $onlineTtl = max(30, (int) config('messaging.presence.ttl_seconds', 90));
        $conversationTtl = max(15, (int) config('messaging.presence.conversation_ttl_seconds', 45));

        if ($previousConversationId && $previousConversationId !== $conversationId) {
            $store->forget($this->conversationKey($previousConversationId, $userId));
        }

        $store->put($onlineKey, [
            'conversation_id' => $conversationId,
            'seen_at' => now()->toIso8601String(),
        ], now()->addSeconds($onlineTtl));

        if ($conversationId) {
            $store->put($this->conversationKey($conversationId, $userId), now()->toIso8601String(), now()->addSeconds($conversationTtl));
        }
    }

    public function isUserOnline(int $userId): bool
    {
        return $this->store()->has($this->onlineKey($userId));
    }

    public function isViewingConversation(int $conversationId, int $userId): bool
    {
        return $this->store()->has($this->conversationKey($conversationId, $userId));
    }

    private function onlineKey(int $userId): string
    {
        return 'messages:presence:user:' . $userId;
    }

    private function conversationKey(int $conversationId, int $userId): string
    {
        return 'messages:presence:conversation:' . $conversationId . ':user:' . $userId;
    }

    private function store(): Repository
    {
        $store = (string) config('messaging.presence.cache_store', 'redis');

        if ($store === 'redis' && ! class_exists('Redis')) {
            return Cache::store();
        }

        try {
            return Cache::store($store);
        } catch (\Throwable) {
            return Cache::store();
        }
    }
}
