<?php

use App\Models\Label;
use App\Models\Song;
use App\Models\SongArrangement;
use App\Models\SongArrangementLabel;
use App\Models\User;

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

test('show returns song with full detail for modal', function () {
    $song = Song::factory()->create([
        'title' => 'Großer Gott wir loben Dich',
        'ccli_id' => '100200',
        'copyright_text' => '© Public Domain',
    ]);

    $label1 = Label::factory()->create([
        'name' => 'Strophe 1',
        'color' => '#3B82F6',
    ]);

    $label2 = Label::factory()->create([
        'name' => 'Refrain',
        'color' => '#10B981',
    ]);
    $section1 = songSectionFor($song, $label1, 1);
    $section2 = songSectionFor($song, $label2, 2);

    $arrangement = SongArrangement::factory()->create([
        'song_id' => $song->id,
        'name' => 'Normal',
        'is_default' => true,
    ]);

    SongArrangementLabel::factory()->create([
        'song_arrangement_id' => $arrangement->id,
        'song_section_id' => $section1->id,
        'order' => 1,
    ]);

    SongArrangementLabel::factory()->create([
        'song_arrangement_id' => $arrangement->id,
        'song_section_id' => $section2->id,
        'order' => 2,
    ]);

    $response = $this->actingAs($this->user)
        ->getJson("/api/songs/{$song->id}");

    $response->assertOk()
        ->assertJsonPath('data.title', 'Großer Gott wir loben Dich')
        ->assertJsonPath('data.ccli_id', '100200')
        ->assertJsonPath('data.copyright_text', '© Public Domain')
        ->assertJsonStructure([
            'data' => [
                'id', 'title', 'ccli_id', 'copyright_text',
                'groups' => [['id', 'name', 'color', 'order', 'slides']],
                'arrangements' => [['id', 'name', 'is_default', 'arrangement_groups']],
            ],
        ]);

    expect($response->json('data.groups.0.name'))->toBe('Strophe 1');
    expect($response->json('data.groups.1.name'))->toBe('Refrain');

    expect($response->json('data.arrangements.0.name'))->toBe('Normal');
    expect($response->json('data.arrangements.0.arrangement_groups'))->toHaveCount(2);
});

test('update saves title via auto-save', function () {
    $song = Song::factory()->create(['title' => 'Original Title']);

    $response = $this->actingAs($this->user)
        ->putJson("/api/songs/{$song->id}", [
            'title' => 'Neuer Titel',
        ]);

    $response->assertOk()
        ->assertJsonFragment(['message' => 'Song erfolgreich aktualisiert']);

    $song->refresh();
    expect($song->title)->toBe('Neuer Titel');
});

test('update saves ccli_id via auto-save', function () {
    $song = Song::factory()->create(['ccli_id' => '111111']);

    $response = $this->actingAs($this->user)
        ->putJson("/api/songs/{$song->id}", [
            'title' => $song->title,
            'ccli_id' => '999888',
        ]);

    $response->assertOk();

    $song->refresh();
    expect($song->ccli_id)->toBe('999888');
});

test('update saves copyright_text via auto-save', function () {
    $song = Song::factory()->create(['copyright_text' => null]);

    $response = $this->actingAs($this->user)
        ->putJson("/api/songs/{$song->id}", [
            'title' => $song->title,
            'copyright_text' => '© 2024 Neuer Copyright-Text',
        ]);

    $response->assertOk();

    $song->refresh();
    expect($song->copyright_text)->toBe('© 2024 Neuer Copyright-Text');
});

test('update can clear optional fields with null', function () {
    $song = Song::factory()->create([
        'ccli_id' => '555555',
        'copyright_text' => 'Some copyright',
    ]);

    $response = $this->actingAs($this->user)
        ->putJson("/api/songs/{$song->id}", [
            'title' => $song->title,
            'ccli_id' => null,
            'copyright_text' => null,
        ]);

    $response->assertOk();

    $song->refresh();
    expect($song->ccli_id)->toBeNull();
    expect($song->copyright_text)->toBeNull();
});

test('update returns full song detail with arrangements', function () {
    $song = Song::factory()->create();
    SongArrangement::factory()->create(['song_id' => $song->id, 'is_default' => true]);

    $response = $this->actingAs($this->user)
        ->putJson("/api/songs/{$song->id}", [
            'title' => 'Updated Song',
        ]);

    $response->assertOk()
        ->assertJsonStructure([
            'data' => [
                'id', 'title', 'ccli_id', 'copyright_text',
                'groups', 'arrangements',
            ],
        ]);
});

test('update validates title is required', function () {
    $song = Song::factory()->create();

    $response = $this->actingAs($this->user)
        ->putJson("/api/songs/{$song->id}", [
            'title' => '',
        ]);

    $response->assertUnprocessable()
        ->assertJsonValidationErrors(['title']);
});

test('update validates unique ccli_id against other songs', function () {
    Song::factory()->create(['ccli_id' => '777777']);
    $song = Song::factory()->create(['ccli_id' => '888888']);

    $response = $this->actingAs($this->user)
        ->putJson("/api/songs/{$song->id}", [
            'title' => $song->title,
            'ccli_id' => '777777',
        ]);

    $response->assertUnprocessable()
        ->assertJsonValidationErrors(['ccli_id']);
});

test('update requires authentication', function () {
    $song = Song::factory()->create();

    $response = $this->putJson("/api/songs/{$song->id}", [
        'title' => 'Should Fail',
    ]);

    $response->assertUnauthorized();
});

test('show returns 404 for soft-deleted song', function () {
    $song = Song::factory()->create(['deleted_at' => now()]);

    $response = $this->actingAs($this->user)
        ->getJson("/api/songs/{$song->id}");

    $response->assertNotFound();
});

test('update returns 404 for nonexistent song', function () {
    $response = $this->actingAs($this->user)
        ->putJson('/api/songs/99999', [
            'title' => 'Ghost Song',
        ]);

    $response->assertNotFound();
});
