<?php

namespace Tests\Feature;

use App\Models\Category;
use App\Models\Setting;
use App\Services\AnalyticsService;
use App\Jobs\SendMetaCapiEvent;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Queue;
use Tests\TestCase;

class AnalyticsSystemTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        // Clear settings file cache before each test for isolation
        \App\Models\Setting::clearCache();
    }

    /**
     * Test that standalone GA4 script appears in head when google_analytics_id is configured.
     */
    public function test_ga4_standalone_snippet_renders_in_layout()
    {
        // 1. Verify not present by default
        $response = $this->get('/');
        $response->assertDontSee('googletagmanager.com/gtag/js');

        // 2. Set config and verify it appears (clearCache is called inside setValue)
        Setting::setValue('google_analytics_id', 'G-TESTGA4', 'analytics');

        $response = $this->get('/');
        $response->assertSee('googletagmanager.com/gtag/js?id=G-TESTGA4');
        $response->assertSee("gtag('config', 'G-TESTGA4');", false);
    }

    /**
     * Test that AnalyticsService correctly extracts fbp and fbc cookies.
     */
    public function test_analytics_service_extracts_fbp_and_fbc_cookies()
    {
        // Simulate cookies on the request
        $this->withUnencryptedCookies([
            '_fbp' => 'fb.1.1596403881.123456789',
            '_fbc' => 'fb.1.1596403881.AbCdEfGhIjKl'
        ]);

        // Hit a dummy route or make any request to bind request instance with cookies
        $this->get('/');

        $userData = AnalyticsService::getUserData();

        $this->assertArrayHasKey('fbp', $userData);
        $this->assertArrayHasKey('fbc', $userData);
        $this->assertEquals('fb.1.1596403881.123456789', $userData['fbp']);
        $this->assertEquals('fb.1.1596403881.AbCdEfGhIjKl', $userData['fbc']);
    }

    /**
     * Test that trackViewCategory dispatches CAPI Job correctly.
     */
    public function test_track_view_category_dispatches_capi_job()
    {
        Bus::fake();

        $category = Category::create([
            'name' => 'Tech & Gadgets',
            'slug' => 'tech-gadgets',
            'is_visible' => true,
        ]);

        AnalyticsService::trackViewCategory($category, 'test-cat-event-id');

        Bus::assertDispatched(SendMetaCapiEvent::class, function ($job) use ($category) {
            // Retrieve reflection parameters if protected
            $refJob = new \ReflectionClass($job);
            
            $eventName = $refJob->getProperty('eventName')->getValue($job);
            $eventId = $refJob->getProperty('eventId')->getValue($job);
            $customData = $refJob->getProperty('customData')->getValue($job);

            return $eventName === 'ViewContent' 
                && $eventId === 'test-cat-event-id' 
                && isset($customData['content_type']) 
                && $customData['content_type'] === 'product_group' 
                && $customData['content_ids'][0] === (string)$category->id;
        });
    }

    /**
     * Test that SendMetaCapiEvent has correct retries configuration and throws exception on failed API.
     */
    public function test_meta_capi_job_retries_and_throws_exception_on_failure()
    {
        Setting::setValue('meta_pixel_id', '123456789', 'analytics');
        Setting::setValue('meta_capi_token', 'capi-token', 'analytics');

        $job = new SendMetaCapiEvent(
            'ViewContent',
            'evt_123',
            ['em' => ['hashed_email']],
            ['value' => 500],
            'https://example.com'
        );

        $this->assertEquals(3, $job->tries);
        $this->assertEquals([10, 30, 60], $job->backoff());

        // Fake Meta API to fail
        Http::fake([
            'graph.facebook.com/*' => Http::response('Server Error', 500)
        ]);

        $this->expectException(\Exception::class);
        $this->expectExceptionMessage('Meta CAPI transmission failed: Server Error');

        $job->handle();
    }
}
