<?php

namespace Tests\Feature;

use App\Agent\MarketingAgent;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Tests\TestCase;

class ChatStreamingTest extends TestCase
{
    use RefreshDatabase;

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

        $this->user = User::factory()->create();
        $this->actingAs($this->user);

        MarketingAgent::fake(['Hello from stream!']);
    }

    public function test_send_returns_streamed_response_when_accepting_event_stream(): void
    {
        $response = $this->post(
            route('chat.send'),
            ['message' => 'Hello there'],
            ['Accept' => 'text/event-stream']
        );

        $response->assertOk();
        $this->assertInstanceOf(StreamedResponse::class, $response->baseResponse);
        $this->assertStringContainsString('text/event-stream', $response->headers->get('Content-Type'));

        ob_start();
        $response->sendContent();
        $content = ob_get_clean();

        $this->assertStringContainsString('data: ', $content);
        $this->assertStringContainsString('"type":"delta"', $content);
        $this->assertStringContainsString('"delta":"Hello"', $content);
        $this->assertStringContainsString('"type":"done"', $content);
        $this->assertStringContainsString('[DONE]', $content);
    }

    public function test_send_returns_json_response_when_accepting_json(): void
    {
        $response = $this->postJson(route('chat.send'), [
            'message' => 'Hello there',
        ]);

        $response->assertOk()
            ->assertJsonStructure(['conversation', 'reply', 'replyHtml', 'choices']);
    }

    public function test_send_does_not_stream_for_wildcard_or_missing_accept_header(): void
    {
        // Accept: */* must return JSON, not SSE
        $wildcard = $this->post(
            route('chat.send'),
            ['message' => 'Hello there'],
            ['Accept' => '*/*']
        );

        $wildcard->assertOk();
        $this->assertStringNotContainsString('text/event-stream', (string) $wildcard->headers->get('Content-Type'));
        $wildcard->assertJsonStructure(['conversation', 'reply']);

        // Missing Accept header must return JSON, not SSE
        $missing = $this->post(
            route('chat.send'),
            ['message' => 'Hello there'],
            []
        );

        $missing->assertOk();
        $this->assertStringNotContainsString('text/event-stream', (string) $missing->headers->get('Content-Type'));
        $missing->assertJsonStructure(['conversation', 'reply']);
    }

    public function test_send_streams_when_stream_boolean_parameter_is_passed(): void
    {
        $response = $this->post(
            route('chat.send'),
            ['message' => 'Hello there', 'stream' => '1'],
            ['Accept' => 'application/json']
        );

        $response->assertOk();
        $this->assertInstanceOf(StreamedResponse::class, $response->baseResponse);
    }
}
