<?php

use App\Models\ServiceAgendaItem;
use App\Services\AgendaMatcherService;

beforeEach(function () {
    $this->service = new AgendaMatcherService;
});

// Exact match
test('matches exact title', function () {
    expect($this->service->matches('Predigt', 'Predigt'))->toBeTrue();
});

// Wildcard suffix
test('matches wildcard suffix pattern', function () {
    expect($this->service->matches('Predigt – Thema XY', 'Predigt*'))->toBeTrue();
});

// Wildcard prefix
test('matches wildcard prefix pattern', function () {
    expect($this->service->matches('Die Predigt', '*Predigt'))->toBeTrue();
});

// Wildcard both
test('matches wildcard both sides pattern', function () {
    expect($this->service->matches('Die Predigt heute', '*Predigt*'))->toBeTrue();
});

// Case insensitive
test('matches case insensitive', function () {
    expect($this->service->matches('Predigt – Thema', 'predigt*'))->toBeTrue();
});

// No match
test('does not match unrelated title', function () {
    expect($this->service->matches('Lobpreis', 'Predigt*'))->toBeFalse();
});

// Multiple patterns — matchesAny
test('matchesAny returns true if any pattern matches', function () {
    $patterns = ['Predigt*', 'Sermon*'];
    expect($this->service->matchesAny('Predigt – Thema', $patterns))->toBeTrue();
});

test('matchesAny returns false if no pattern matches', function () {
    $patterns = ['Predigt*', 'Sermon*'];
    expect($this->service->matchesAny('Lobpreis', $patterns))->toBeFalse();
});

// findFirstMatch returns matching item
test('findFirstMatch returns first matching ServiceAgendaItem', function () {
    $items = [
        ServiceAgendaItem::factory()->create(['title' => 'Lobpreis']),
        ServiceAgendaItem::factory()->create(['title' => 'Predigt – Thema']),
        ServiceAgendaItem::factory()->create(['title' => 'Gebet']),
    ];

    $result = $this->service->findFirstMatch($items, 'Predigt*');

    expect($result)->toBeInstanceOf(ServiceAgendaItem::class);
    expect($result->title)->toBe('Predigt – Thema');
});

test('findFirstMatch returns null when no match', function () {
    $items = [
        ServiceAgendaItem::factory()->create(['title' => 'Lobpreis']),
        ServiceAgendaItem::factory()->create(['title' => 'Gebet']),
    ];

    $result = $this->service->findFirstMatch($items, 'Predigt*');

    expect($result)->toBeNull();
});

// filterBetween with both start and end
test('filterBetween filters items between start and end (both excluded)', function () {
    $items = [
        ServiceAgendaItem::factory()->create(['title' => 'Info']),
        ServiceAgendaItem::factory()->create(['title' => 'Start']),
        ServiceAgendaItem::factory()->create(['title' => 'Lied 1']),
        ServiceAgendaItem::factory()->create(['title' => 'Lied 2']),
        ServiceAgendaItem::factory()->create(['title' => 'End']),
        ServiceAgendaItem::factory()->create(['title' => 'Segen']),
    ];

    $result = $this->service->filterBetween($items, 'Start', 'End');

    expect($result)->toHaveCount(2);
    expect($result[0]->title)->toBe('Lied 1');
    expect($result[1]->title)->toBe('Lied 2');
});

// filterBetween with start only
test('filterBetween from start boundary to end of items', function () {
    $items = [
        ServiceAgendaItem::factory()->create(['title' => 'Info']),
        ServiceAgendaItem::factory()->create(['title' => 'Start']),
        ServiceAgendaItem::factory()->create(['title' => 'Lied 1']),
        ServiceAgendaItem::factory()->create(['title' => 'Lied 2']),
    ];

    $result = $this->service->filterBetween($items, 'Start', null);

    expect($result)->toHaveCount(2);
    expect($result[0]->title)->toBe('Lied 1');
    expect($result[1]->title)->toBe('Lied 2');
});

// filterBetween with neither
test('filterBetween with no start or end patterns returns all items', function () {
    $items = [
        ServiceAgendaItem::factory()->create(['title' => 'Info']),
        ServiceAgendaItem::factory()->create(['title' => 'Lied 1']),
        ServiceAgendaItem::factory()->create(['title' => 'Lied 2']),
    ];

    $result = $this->service->filterBetween($items, null, null);

    expect($result)->toHaveCount(3);
});

// filterBetween with no matching start
test('filterBetween with no matching start pattern returns empty array', function () {
    $items = [
        ServiceAgendaItem::factory()->create(['title' => 'Lied 1']),
        ServiceAgendaItem::factory()->create(['title' => 'Lied 2']),
    ];

    $result = $this->service->filterBetween($items, 'Nonexistent*', null);

    expect($result)->toBeEmpty();
});

// findFirstMatch with comma-separated patterns
test('findFirstMatch splits comma-separated patterns and matches', function () {
    $items = [
        ServiceAgendaItem::factory()->create(['title' => 'Lobpreis']),
        ServiceAgendaItem::factory()->create(['title' => 'Predigt – Thema']),
    ];

    $result = $this->service->findFirstMatch($items, 'Lied*,Predigt*');

    expect($result)->toBeInstanceOf(ServiceAgendaItem::class);
    expect($result->title)->toBe('Predigt – Thema');
});

// Edge case: empty items array
test('findFirstMatch with empty items returns null', function () {
    $result = $this->service->findFirstMatch([], 'Predigt*');

    expect($result)->toBeNull();
});

test('filterBetween with empty items returns empty array', function () {
    $result = $this->service->filterBetween([], 'Start', 'End');

    expect($result)->toBeEmpty();
});
