<?php

use App\Models\Label;
use App\Models\Song;
use App\Models\SongArrangement;
use App\Models\SongArrangementLabel;
use App\Models\SongSection;
use App\Models\SongSlide;
use App\Services\CcliTranslationPairingService;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

function makeLocalSongForCcliPairing(array $labelConfig): Song
{
    $song = Song::factory()->create();
    $arrangement = SongArrangement::factory()->create([
        'song_id' => $song->id,
        'name' => 'normal',
        'is_default' => true,
    ]);

    foreach ($labelConfig as $order => $config) {
        ['label_name' => $labelName, 'slide_count' => $slideCount] = $config;

        $label = Label::firstOrCreate(
            ['name' => $labelName],
            ['color' => '#3B82F6'],
        );
        $section = SongSection::create([
            'song_id' => $song->id,
            'label_id' => $label->id,
            'order' => $order + 1,
        ]);

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

        for ($i = 0; $i < $slideCount; $i++) {
            SongSlide::create([
                'song_section_id' => $section->id,
                'order' => $i + 1,
                'text_content' => "Original line $i for $labelName",
            ]);
        }
    }

    return $song;
}

test('pairs matching English labels with CCLI sections', function (): void {
    $song = makeLocalSongForCcliPairing([
        ['label_name' => 'Verse 1', 'slide_count' => 2],
        ['label_name' => 'Chorus', 'slide_count' => 1],
        ['label_name' => 'Verse 2', 'slide_count' => 2],
    ]);

    $ccliText = "Test Song\nTest Artist\n\nVerse 1\nCCLI line 1\nCCLI line 2\n\nChorus\nCCLI chorus\n\nVerse 2\nCCLI v2 line1\nCCLI v2 line2\n\n© 2024 Test\nCCLI # 9999001";

    $result = app(CcliTranslationPairingService::class)->pair($song, $ccliText);

    expect($result['unmatched_labels'])->toBeEmpty('All labels should match')
        ->and($result['mapping'])->toHaveCount(3)
        ->and($result['distributed_text'])->not->toBeEmpty();

    foreach ($result['mapping'] as $entry) {
        expect($entry['ccli_label'])->not->toBeNull("Label {$entry['local_label']} should have a CCLI match");
    }
});

test('pairs German local labels with English CCLI labels via normalization', function (): void {
    $song = makeLocalSongForCcliPairing([
        ['label_name' => 'Strophe 1', 'slide_count' => 2],
        ['label_name' => 'Refrain', 'slide_count' => 2],
        ['label_name' => 'Strophe 2', 'slide_count' => 2],
    ]);

    $ccliText = "Test Song\nTest Artist\n\nVerse 1\nEN line 1\nEN line 2\n\nChorus\nEN chorus 1\nEN chorus 2\n\nVerse 2\nEN v2 1\nEN v2 2\n\n© 2024 Test\nCCLI # 9999002";

    $result = app(CcliTranslationPairingService::class)->pair($song, $ccliText);

    expect($result['unmatched_labels'])->toBeEmpty('German labels should normalize to match English CCLI labels')
        ->and($result['mapping'])->toHaveCount(3)
        ->and($result['mapping'][0]['ccli_label'])->toBe('Verse 1')
        ->and($result['mapping'][1]['ccli_label'])->toBe('Chorus');
});

test('returns unmatched_labels for sections not in CCLI', function (): void {
    $song = makeLocalSongForCcliPairing([
        ['label_name' => 'Verse 1', 'slide_count' => 2],
        ['label_name' => 'Chorus', 'slide_count' => 1],
        ['label_name' => 'Bridge', 'slide_count' => 2],
    ]);

    $ccliText = "Test Song\nTest Artist\n\nVerse 1\nLine 1\nLine 2\n\nChorus\nChorus line\n\n© 2024 Test\nCCLI # 9999003";

    $result = app(CcliTranslationPairingService::class)->pair($song, $ccliText);

    expect($result['unmatched_labels'])->toContain('Bridge')
        ->and($result['mapping'])->toHaveCount(3)
        ->and($result['mapping'][2]['ccli_label'])->toBeNull()
        ->and($result['mapping'][2]['distributed_lines'])->toBe(['', '']);
});

test('distributes lines preserving local slide count', function (): void {
    $song = makeLocalSongForCcliPairing([
        ['label_name' => 'Verse 1', 'slide_count' => 2],
    ]);

    $ccliText = "Test Song\nTest Artist\n\nVerse 1\nLine 1\nLine 2\nLine 3\nLine 4\n\n© 2024\nCCLI # 9999004";

    $result = app(CcliTranslationPairingService::class)->pair($song, $ccliText);

    expect($result['mapping'][0]['distributed_lines'])->toHaveCount(2)
        ->and($result['distributed_text'])->toContain('Line 4');
});

test('uses linesTranslated from CCLI when available', function (): void {
    $song = makeLocalSongForCcliPairing([
        ['label_name' => 'Verse 1', 'slide_count' => 2],
        ['label_name' => 'Chorus', 'slide_count' => 1],
    ]);

    $ccliText = file_get_contents(base_path('tests/fixtures/ccli/english-german-side-by-side.txt'));

    $result = app(CcliTranslationPairingService::class)->pair($song, $ccliText);

    expect($result['song'])->toBeInstanceOf(Song::class)
        ->and($result['mapping'])->toBeArray()
        ->and($result['distributed_text'])->toContain('Deutsche Liedzeile')
        ->and($result['distributed_text'])->toContain('Deutscher Refrain');
});
