<?php

use App\Services\CcliPasteParser;
use App\Services\DTO\ParsedCcliSection;
use App\Services\DTO\ParsedCcliSong;

test('CcliPasteParser can be instantiated with no arguments', function (): void {
    $parser = new CcliPasteParser;

    expect($parser)->toBeInstanceOf(CcliPasteParser::class);
});

test('CcliPasteParser can be instantiated with closure injections', function (): void {
    $parser = new CcliPasteParser(
        sectionDetector: fn (string $line): bool => str_starts_with($line, 'Verse'),
        metadataDetector: fn (string $line): bool => str_contains($line, '©'),
    );

    expect($parser)->toBeInstanceOf(CcliPasteParser::class);
});

test('CcliPasteParser resolves from Laravel container', function (): void {
    $parser = app(CcliPasteParser::class);

    expect($parser)->toBeInstanceOf(CcliPasteParser::class);
});

test('CcliPasteParser::parse returns ParsedCcliSong DTO', function (): void {
    $parser = new CcliPasteParser;

    $result = $parser->parse("Test Song\nTest Artist\n\nVerse 1\nSome text");

    expect($result)->toBeInstanceOf(ParsedCcliSong::class);
});

test('ParsedCcliSong DTO has all required properties', function (): void {
    $song = new ParsedCcliSong(
        title: 'Test Song',
        author: 'Test Author',
        ccliId: '9999001',
        year: '2024',
        copyrightText: '© 2024 Test',
        sourceUrl: 'https://songselect.ccli.com/Songs/9999001',
        sections: [],
    );

    expect($song->title)->toBe('Test Song');
    expect($song->author)->toBe('Test Author');
    expect($song->ccliId)->toBe('9999001');
    expect($song->year)->toBe('2024');
    expect($song->copyrightText)->toBe('© 2024 Test');
    expect($song->sourceUrl)->toContain('songselect.ccli.com');
    expect($song->sections)->toBeArray();
});

test('ParsedCcliSection DTO has all required properties including linesTranslated', function (): void {
    $section = new ParsedCcliSection(
        label: 'Verse 1',
        kind: 'Verse',
        number: '1',
        modifier: null,
        lines: ['Line 1', 'Line 2'],
        linesTranslated: ['Zeile 1', 'Zeile 2'],
    );

    expect($section->label)->toBe('Verse 1');
    expect($section->kind)->toBe('Verse');
    expect($section->number)->toBe('1');
    expect($section->modifier)->toBeNull();
    expect($section->lines)->toBe(['Line 1', 'Line 2']);
    expect($section->linesTranslated)->toBe(['Zeile 1', 'Zeile 2']);
});

test('ParsedCcliSection linesTranslated defaults to null', function (): void {
    $section = new ParsedCcliSection(
        label: 'Chorus',
        kind: 'Chorus',
        number: null,
        modifier: null,
        lines: ['Line 1'],
    );

    expect($section->linesTranslated)->toBeNull();
});

test('CcliPasteParser can be injected with closure override in container', function (): void {
    $called = false;
    $fakeParser = new CcliPasteParser(
        sectionDetector: function () use (&$called): bool {
            $called = true;

            return true;
        },
    );

    app()->instance(CcliPasteParser::class, $fakeParser);
    $resolved = app(CcliPasteParser::class);

    expect($resolved)->toBe($fakeParser);

    app()->forgetInstance(CcliPasteParser::class);
});
