<?php

namespace Tests\Feature;

use App\Models\Category;
use App\Models\Product;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;

class AssistantApiTest extends TestCase
{
    use RefreshDatabase;

    protected User $user;

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

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

    public function test_guest_can_chat_with_assistant(): void
    {
        $response = $this->postJson('/api/v1/assistant/chat', [
            'message' => 'What are the best deals today?',
        ]);

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'data' => [
                    'response',
                    'suggestions',
                    'session_id',
                ],
                'metadata',
            ]);
    }

    public function test_guest_can_use_session_id_for_continuity(): void
    {
        $sessionId = 'test_session_123';

        $response = $this->postJson('/api/v1/assistant/chat', [
            'message' => 'Show me deals',
            'session_id' => $sessionId,
        ]);

        $response->assertStatus(200)
            ->assertJsonPath('data.session_id', $sessionId);
    }

    public function test_authenticated_user_can_chat(): void
    {
        Sanctum::actingAs($this->user);

        $response = $this->postJson('/api/v1/assistant/chat', [
            'message' => 'Find products under $100',
        ]);

        $response->assertStatus(200)
            ->assertJsonPath('success', true);
    }

    public function test_chat_requires_message(): void
    {
        $response = $this->postJson('/api/v1/assistant/chat', []);

        $response->assertStatus(422)
            ->assertJsonValidationErrors(['message']);
    }

    public function test_chat_message_cannot_be_empty(): void
    {
        $response = $this->postJson('/api/v1/assistant/chat', [
            'message' => '',
        ]);

        $response->assertStatus(422)
            ->assertJsonValidationErrors(['message']);
    }

    public function test_chat_message_max_length(): void
    {
        $response = $this->postJson('/api/v1/assistant/chat', [
            'message' => str_repeat('a', 2001),
        ]);

        $response->assertStatus(422)
            ->assertJsonValidationErrors(['message']);
    }

    public function test_authenticated_user_can_get_history(): void
    {
        Sanctum::actingAs($this->user);

        $this->postJson('/api/v1/assistant/chat', [
            'message' => 'Test message',
        ]);

        $response = $this->getJson('/api/v1/assistant/history');

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'data' => [
                    'history',
                    'total',
                ],
            ])
            ->assertJsonPath('success', true);
    }

    public function test_guest_can_get_history_with_session_id(): void
    {
        $sessionId = 'test_session_456';

        $this->postJson('/api/v1/assistant/chat', [
            'message' => 'Test message',
            'session_id' => $sessionId,
        ]);

        $response = $this->getJson('/api/v1/assistant/history?session_id='.$sessionId);

        $response->assertStatus(200)
            ->assertJsonPath('success', true);
    }

    public function test_history_requires_auth_or_session_id(): void
    {
        $response = $this->getJson('/api/v1/assistant/history');

        $response->assertStatus(400)
            ->assertJsonPath('success', false);
    }

    public function test_authenticated_user_can_clear_history(): void
    {
        Sanctum::actingAs($this->user);

        $this->postJson('/api/v1/assistant/chat', [
            'message' => 'Test message',
        ]);

        $response = $this->deleteJson('/api/v1/assistant/history');

        $response->assertStatus(200)
            ->assertJsonPath('success', true);
    }

    public function test_guest_can_clear_history_with_session_id(): void
    {
        $sessionId = 'test_session_789';

        $this->postJson('/api/v1/assistant/chat', [
            'message' => 'Test message',
            'session_id' => $sessionId,
        ]);

        $response = $this->deleteJson('/api/v1/assistant/history', [
            'session_id' => $sessionId,
        ]);

        $response->assertStatus(200)
            ->assertJsonPath('success', true);
    }

    public function test_anyone_can_get_suggestions(): void
    {
        $response = $this->getJson('/api/v1/assistant/suggestions');

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'data' => [
                    'suggestions',
                    'count',
                ],
            ])
            ->assertJsonPath('success', true)
            ->assertJsonIsArray('data.suggestions');
    }

    public function test_suggestions_are_helpful(): void
    {
        $response = $this->getJson('/api/v1/assistant/suggestions');

        $suggestions = $response->json('data.suggestions');

        $this->assertIsArray($suggestions);
        $this->assertNotEmpty($suggestions);
        $this->assertContains('Find the best deals today', $suggestions);
    }

    public function test_assistant_handles_product_comparison(): void
    {
        $category = Category::factory()->create();
        $products = Product::factory()->count(3)->create([
            'category_id' => $category->id,
        ]);

        Sanctum::actingAs($this->user);

        $response = $this->postJson('/api/v1/assistant/chat', [
            'message' => "Compare products {$products[0]->id}, {$products[1]->id}, and {$products[2]->id}",
        ]);

        $response->assertStatus(200)
            ->assertJsonPath('success', true);
    }

    public function test_assistant_handles_deal_requests(): void
    {
        Product::factory()->create([
            'discount' => 25.50,
            'price' => 100,
        ]);

        $response = $this->postJson('/api/v1/assistant/chat', [
            'message' => 'Show me the best deals',
        ]);

        $response->assertStatus(200)
            ->assertJsonPath('success', true);
    }

    public function test_assistant_handles_recommendation_requests(): void
    {
        Product::factory()->count(5)->create([
            'positive_feedback' => 90,
            'sales_180day' => 100,
        ]);

        $response = $this->postJson('/api/v1/assistant/chat', [
            'message' => 'Recommend some products for me',
        ]);

        $response->assertStatus(200)
            ->assertJsonPath('success', true);
    }

    public function test_rate_limiting_works_for_guests(): void
    {
        $responses = [];

        for ($i = 0; $i < 11; $i++) {
            $responses[] = $this->postJson('/api/v1/assistant/chat', [
                'message' => 'Test message '.$i,
            ]);
        }

        $this->assertTrue($responses[10]->status() === 429);
    }

    public function test_authenticated_users_not_rate_limited(): void
    {
        Sanctum::actingAs($this->user);

        for ($i = 0; $i < 15; $i++) {
            $response = $this->postJson('/api/v1/assistant/chat', [
                'message' => 'Test message '.$i,
            ]);

            $this->assertNotEquals(429, $response->status());
        }
    }

    public function test_conversation_context_persists(): void
    {
        Sanctum::actingAs($this->user);

        $this->postJson('/api/v1/assistant/chat', [
            'message' => 'I am looking for a laptop',
        ]);

        $response = $this->postJson('/api/v1/assistant/chat', [
            'message' => 'What are the options under $1000?',
        ]);

        $response->assertStatus(200);
    }
}
