<?php

use App\Models\Service;
use App\Models\ServiceSong;
use App\Models\Song;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

function ccliPasteControllerFixture(string $name): string
{
    return file_get_contents(base_path("tests/fixtures/ccli/{$name}"));
}

test('preview returns parsed DTO without writing to DB', function () {
    $user = User::factory()->create();
    $content = ccliPasteControllerFixture('english-only-multi-verse.txt');

    $songCountBefore = Song::count();

    $response = $this->actingAs($user)
        ->postJson(route('api.ccli.preview'), ['raw_text' => $content]);

    $response->assertStatus(200);
    $response->assertJsonStructure(['title', 'author', 'ccliId', 'year', 'copyrightText', 'sections']);
    expect($response->json('title'))->toBe('Test Song 1');
    expect($response->json('ccliId'))->toBe('9999001');
    expect(Song::count())->toBe($songCountBefore);
});

test('importPaste create mode persists song and returns 201', function () {
    $user = User::factory()->create();
    $content = ccliPasteControllerFixture('english-only-multi-verse.txt');

    $response = $this->actingAs($user)
        ->postJson(route('api.ccli.import'), [
            'raw_text' => $content,
            'mode' => 'create',
        ]);

    $response->assertStatus(201);
    $response->assertJsonStructure(['song_id', 'status', 'warnings']);
    expect($response->json('status'))->toBe('created');
    expect(Song::find($response->json('song_id')))->not->toBeNull();
});

test('importPaste returns 409 on duplicate ccli_id with existing_song_id', function () {
    $user = User::factory()->create();
    $content = ccliPasteControllerFixture('english-only-multi-verse.txt');

    $first = $this->actingAs($user)
        ->postJson(route('api.ccli.import'), ['raw_text' => $content, 'mode' => 'create']);
    $existingId = $first->json('song_id');

    $response = $this->actingAs($user)
        ->postJson(route('api.ccli.import'), ['raw_text' => $content, 'mode' => 'create']);

    $response->assertStatus(409);
    $response->assertJsonStructure(['message', 'existing_song_id', 'edit_url']);
    expect($response->json('existing_song_id'))->toBe($existingId);
    expect($response->json('message'))->toContain('existiert bereits');
});

test('importPaste returns 422 on malformed paste with German error', function () {
    $user = User::factory()->create();

    $response = $this->actingAs($user)
        ->postJson(route('api.ccli.import'), [
            'raw_text' => 'This has no section labels at all',
            'mode' => 'create',
        ]);

    $response->assertStatus(422);
    $response->assertJsonStructure(['message']);
    expect($response->json('message'))->not->toBeEmpty();
});

test('importPaste returns 422 on empty raw_text', function () {
    $user = User::factory()->create();

    $response = $this->actingAs($user)
        ->postJson(route('api.ccli.import'), [
            'raw_text' => '',
            'mode' => 'create',
        ]);

    $response->assertStatus(422);
});

test('importPaste assign-to-service-song imports and assigns song to service song', function () {
    $user = User::factory()->create();
    $content = ccliPasteControllerFixture('english-only-multi-verse.txt');

    $service = Service::factory()->create();
    $serviceSong = ServiceSong::factory()->create([
        'service_id' => $service->id,
        'song_id' => null,
        'song_arrangement_id' => null,
        'matched_at' => null,
    ]);

    $response = $this->actingAs($user)
        ->postJson(route('api.ccli.import'), [
            'raw_text' => $content,
            'mode' => 'assign-to-service-song',
            'target_id' => $serviceSong->id,
        ]);

    $response->assertStatus(201);
    $response->assertJsonStructure(['song_id', 'service_song_id', 'status']);

    $serviceSong->refresh();
    expect($serviceSong->song_id)->toBe($response->json('song_id'));
    expect($serviceSong->matched_at)->not->toBeNull();
});

test('importPaste rejects unauthenticated requests with 401', function () {
    $response = $this->postJson(route('api.ccli.import'), [
        'raw_text' => 'test',
        'mode' => 'create',
    ]);

    $response->assertUnauthorized();
});

test('showImportPage renders Inertia page with prefilled data from valid base64', function () {
    $user = User::factory()->create();
    $this->withoutVite();

    $payload = json_encode([
        'title' => 'Amazing Grace',
        'author' => 'John Newton',
        'ccliId' => '4760',
        'sourceUrl' => 'https://songselect.ccli.com/Songs/4760',
        'rawText' => "Amazing Grace\nJohn Newton\n\nVerse 1\nAmazing grace how sweet the sound\n\n© 1779\nCCLI # 4760",
    ]);
    $encoded = base64_encode($payload);

    $response = $this->actingAs($user)
        ->get(route('songs.import-from-ccli-paste', ['prefill' => $encoded]));

    $response->assertStatus(200);
    $response->assertInertia(
        fn ($page) => $page->component('Songs/ImportFromCcliPaste', false)
            ->has('prefilledText')
            ->has('prefilledMetadata')
            ->where('prefilledMetadata.title', 'Amazing Grace')
            ->where('prefilledMetadata.ccliId', '4760')
    );
});

test('showImportPage renders with error for invalid base64', function () {
    $user = User::factory()->create();
    $this->withoutVite();

    $response = $this->actingAs($user)
        ->get(route('songs.import-from-ccli-paste', ['prefill' => 'NOT_VALID_BASE64!!!']));

    $response->assertStatus(200);
    $response->assertInertia(
        fn ($page) => $page->component('Songs/ImportFromCcliPaste', false)
            ->where('prefillError', fn ($v) => $v !== null)
    );
});

test('showImportPage redirects unauthenticated to login', function () {
    $response = $this->get(route('songs.import-from-ccli-paste'));

    $response->assertRedirect(route('login'));
});
