<?php

declare(strict_types=1);

namespace Tests\Unit\Services\Dashboard;

use App\Services\Dashboard\DashboardCacheService;
use Illuminate\Support\Facades\Cache;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;

class DashboardCacheServiceTest extends TestCase
{
    private DashboardCacheService $service;

    protected function setUp(): void
    {
        parent::setUp();

        Cache::flush();
        $this->service = new DashboardCacheService;
    }

    #[Test]
    public function it_stores_and_retrieves_values()
    {
        $companyId = 1;
        $key = 'test.metric';
        $value = ['foo' => 'bar', 'count' => 42];

        $this->service->put($companyId, $key, $value);

        $retrieved = $this->service->get($companyId, $key);

        $this->assertEquals($value, $retrieved);
    }

    #[Test]
    public function it_remembers_computed_values()
    {
        $companyId = 1;
        $key = 'test.computed';
        $computeCount = 0;

        $compute = function () use (&$computeCount) {
            $computeCount++;

            return ['computed' => true, 'timestamp' => now()->timestamp];
        };

        // Primera llamada: debe computar
        $result1 = $this->service->remember($companyId, $key, $compute);
        $this->assertEquals(1, $computeCount);

        // Segunda llamada: debe usar cache
        $result2 = $this->service->remember($companyId, $key, $compute);
        $this->assertEquals(1, $computeCount); // No debe haber computado de nuevo

        $this->assertEquals($result1, $result2);
    }

    #[Test]
    public function it_forgets_specific_keys()
    {
        $companyId = 1;
        $key = 'test.forget';

        $this->service->put($companyId, $key, 'value');
        $this->assertTrue($this->service->has($companyId, $key));

        $this->service->forget($companyId, $key);
        $this->assertFalse($this->service->has($companyId, $key));
    }

    #[Test]
    public function it_invalidates_multiple_keys()
    {
        $companyId = 1;

        $this->service->put($companyId, 'key1', 'value1');
        $this->service->put($companyId, 'key2', 'value2');
        $this->service->put($companyId, 'key3', 'value3');

        $this->service->invalidateKeys($companyId, ['key1', 'key2']);

        $this->assertFalse($this->service->has($companyId, 'key1'));
        $this->assertFalse($this->service->has($companyId, 'key2'));
        $this->assertTrue($this->service->has($companyId, 'key3'));
    }

    #[Test]
    public function it_isolates_data_by_company()
    {
        $company1 = 1;
        $company2 = 2;
        $key = 'same.key';

        $this->service->put($company1, $key, 'company1_value');
        $this->service->put($company2, $key, 'company2_value');

        $this->assertEquals('company1_value', $this->service->get($company1, $key));
        $this->assertEquals('company2_value', $this->service->get($company2, $key));
    }

    #[Test]
    public function it_uses_preset_ttl_values()
    {
        $companyId = 1;

        // Verificar que los presets no causan errores
        $presets = ['realtime', 'frequent', 'standard', 'slow', 'daily', 'report'];

        foreach ($presets as $preset) {
            $key = "test.{$preset}";
            $this->service->put($companyId, $key, 'value', $preset);
            $this->assertTrue($this->service->has($companyId, $key));
        }
    }

    #[Test]
    public function it_accepts_numeric_ttl()
    {
        $companyId = 1;
        $key = 'test.numeric_ttl';

        $this->service->put($companyId, $key, 'value', 120);
        $this->assertTrue($this->service->has($companyId, $key));
    }

    #[Test]
    public function it_checks_if_key_exists()
    {
        $companyId = 1;

        $this->assertFalse($this->service->has($companyId, 'nonexistent'));

        $this->service->put($companyId, 'exists', 'value');
        $this->assertTrue($this->service->has($companyId, 'exists'));
    }

    #[Test]
    public function it_provides_stats()
    {
        $companyId = 1;

        $stats = $this->service->getStats($companyId);

        $this->assertArrayHasKey('company_id', $stats);
        $this->assertArrayHasKey('prefix', $stats);
        $this->assertArrayHasKey('driver', $stats);
        $this->assertEquals($companyId, $stats['company_id']);
    }
}
