<?php

use App\Enums\ReactionType;
use App\Models\Artwork;
use App\Models\ArtworkComment;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

// ── Comment CRUD ──────────────────────────────────────────────────────────────

test('authenticated user can post a comment', function () {
    $user    = User::factory()->create();
    $artwork = Artwork::factory()->create();

    $this->actingAs($user)
        ->postJson("/api/artworks/{$artwork->id}/comments", [
            'content' => 'Great work! Really love the **colours**.',
        ])
        ->assertStatus(201)
        ->assertJsonPath('data.user.id', $user->id)
        ->assertJsonStructure(['data' => ['id', 'raw_content', 'rendered_content', 'user']]);
});

test('authenticated user can post a comment with emoji', function () {
    $user    = User::factory()->create();
    $artwork = Artwork::factory()->create();

    $this->actingAs($user)
        ->postJson("/api/artworks/{$artwork->id}/comments", [
            'content' => 'Love this 🚀🔥',
        ])
        ->assertStatus(201)
        ->assertJsonPath('data.raw_content', 'Love this 🚀🔥');

    $comment = ArtworkComment::query()->latest('id')->first();

    expect($comment)->not()->toBeNull()
        ->and($comment->raw_content)->toContain('🚀')
        ->and($comment->rendered_content)->toContain('🚀')
        ->and($comment->rendered_content)->toContain('🔥');
});

test('guest cannot post a comment', function () {
    $artwork = Artwork::factory()->create();

    $this->postJson("/api/artworks/{$artwork->id}/comments", ['content' => 'Nice!'])
        ->assertStatus(401);
});

test('comment with raw HTML is rejected via validation', function () {
    $user    = User::factory()->create();
    $artwork = Artwork::factory()->create();

    $this->actingAs($user)
        ->postJson("/api/artworks/{$artwork->id}/comments", [
            'content' => '<script>alert("xss")</script>',
        ])
        ->assertStatus(422);
});

test('user can view comments on public artwork', function () {
    $artwork  = Artwork::factory()->create();
    $comment  = ArtworkComment::factory()->create(['artwork_id' => $artwork->id]);

    $this->getJson("/api/artworks/{$artwork->id}/comments")
        ->assertStatus(200)
        ->assertJsonStructure(['data', 'meta'])
        ->assertJsonCount(1, 'data');
});

// ── Reactions ─────────────────────────────────────────────────────────────────

test('authenticated user can add an artwork reaction', function () {
    $user    = User::factory()->create();
    $artwork = Artwork::factory()->create();

    $this->actingAs($user)
        ->postJson("/api/artworks/{$artwork->id}/reactions", [
            'reaction' => ReactionType::Heart->value,
        ])
        ->assertStatus(200)
        ->assertJsonPath('reaction', ReactionType::Heart->value)
        ->assertJsonPath('active', true);
});

test('reaction is toggled off when posted twice', function () {
    $user    = User::factory()->create();
    $artwork = Artwork::factory()->create();

    // First toggle — on
    $this->actingAs($user)
        ->postJson("/api/artworks/{$artwork->id}/reactions", [
            'reaction' => ReactionType::ThumbsUp->value,
        ])
        ->assertJsonPath('active', true);

    // Second toggle — off
    $this->actingAs($user)
        ->postJson("/api/artworks/{$artwork->id}/reactions", [
            'reaction' => ReactionType::ThumbsUp->value,
        ])
        ->assertJsonPath('active', false);
});

test('guest cannot add a reaction', function () {
    $artwork = Artwork::factory()->create();

    $this->postJson("/api/artworks/{$artwork->id}/reactions", [
        'reaction' => ReactionType::Fire->value,
    ])->assertStatus(401);
});

test('invalid reaction slug is rejected', function () {
    $user    = User::factory()->create();
    $artwork = Artwork::factory()->create();

    $this->actingAs($user)
        ->postJson("/api/artworks/{$artwork->id}/reactions", [
            'reaction' => 'not_valid_slug',
        ])
        ->assertStatus(422);
});

test('reaction totals are returned for public artworks', function () {
    $artwork = Artwork::factory()->create();
    $user    = User::factory()->create();

    // Insert a reaction directly
    \Illuminate\Support\Facades\DB::table('artwork_reactions')->insert([
        'artwork_id' => $artwork->id,
        'user_id'    => $user->id,
        'reaction'   => ReactionType::Clap->value,
        'created_at' => now(),
    ]);

    $this->getJson("/api/artworks/{$artwork->id}/reactions")
        ->assertStatus(200)
        ->assertJsonPath('totals.' . ReactionType::Clap->value . '.count', 1)
        ->assertJsonPath('totals.' . ReactionType::Clap->value . '.emoji', '👏');
});

test('user can react to a comment', function () {
    $user    = User::factory()->create();
    $artwork = Artwork::factory()->create();
    $comment = ArtworkComment::factory()->create(['artwork_id' => $artwork->id]);

    $this->actingAs($user)
        ->postJson("/api/comments/{$comment->id}/reactions", [
            'reaction' => ReactionType::Laugh->value,
        ])
        ->assertStatus(200)
        ->assertJsonPath('active', true)
        ->assertJsonPath('entity_type', 'comment');
});

test('reaction uniqueness per user per slug', function () {
    $user    = User::factory()->create();
    $artwork = Artwork::factory()->create();

    $slug = ReactionType::Wow->value;

    // Toggle on
    $this->actingAs($user)->postJson("/api/artworks/{$artwork->id}/reactions", ['reaction' => $slug]);

    // DB should have exactly 1 row
    $this->assertDatabaseCount('artwork_reactions', 1);

    // Toggle off
    $this->actingAs($user)->postJson("/api/artworks/{$artwork->id}/reactions", ['reaction' => $slug]);

    // DB should have 0 rows
    $this->assertDatabaseCount('artwork_reactions', 0);
});
