<?php

use App\Models\Service;
use App\Models\ServiceAgendaItem;
use App\Models\ServiceSong;
use App\Models\Slide;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Schema;

/*
|--------------------------------------------------------------------------
| ServiceAgendaItem Model & Migration Tests
|--------------------------------------------------------------------------
*/

test('migration creates service_agenda_items table with correct columns', function () {
    expect(Schema::hasTable('service_agenda_items'))->toBeTrue();

    $columns = [
        'id',
        'service_id',
        'cts_agenda_item_id',
        'position',
        'title',
        'type',
        'note',
        'duration',
        'start',
        'is_before_event',
        'responsible',
        'service_song_id',
        'sort_order',
        'created_at',
        'updated_at',
    ];

    foreach ($columns as $column) {
        expect(Schema::hasColumn('service_agenda_items', $column))->toBeTrue();
    }
});

test('factory creates valid service agenda item', function () {
    $item = ServiceAgendaItem::factory()->create();

    expect($item)->toBeInstanceOf(ServiceAgendaItem::class);
    expect($item->id)->toBeGreaterThan(0);
    expect($item->service_id)->toBeGreaterThan(0);
    expect($item->title)->not->toBeNull();
    expect($item->type)->toBeIn(['Song', 'Default', 'Header']);
    expect($item->position)->not->toBeNull();
    expect($item->is_before_event)->toBeFalse();
    expect($item->sort_order)->toBeGreaterThan(0);
});

test('service relationship returns correct service', function () {
    $service = Service::factory()->create();
    $item = ServiceAgendaItem::factory()->create(['service_id' => $service->id]);

    expect($item->service)->toBeInstanceOf(Service::class);
    expect($item->service->id)->toBe($service->id);
});

test('serviceSong relationship is nullable', function () {
    $item = ServiceAgendaItem::factory()->create(['service_song_id' => null]);

    expect($item->serviceSong)->toBeNull();
});

test('serviceSong relationship returns correct service song', function () {
    $song = ServiceSong::factory()->create();
    $item = ServiceAgendaItem::factory()->create(['service_song_id' => $song->id]);

    expect($item->serviceSong)->toBeInstanceOf(ServiceSong::class);
    expect($item->serviceSong->id)->toBe($song->id);
});

test('slides relationship returns associated slides', function () {
    $item = ServiceAgendaItem::factory()->create();
    Slide::factory()->count(3)->create(['service_agenda_item_id' => $item->id]);

    expect($item->slides)->toHaveCount(3);
    expect($item->slides->first())->toBeInstanceOf(Slide::class);
});

test('scopeVisible excludes is_before_event true items', function () {
    ServiceAgendaItem::factory()->count(2)->create(['is_before_event' => false]);
    ServiceAgendaItem::factory()->count(3)->create(['is_before_event' => true]);

    $visible = ServiceAgendaItem::visible()->get();

    expect($visible)->toHaveCount(2);
    $visible->each(fn ($item) => expect($item->is_before_event)->toBeFalse());
});

test('responsible is cast to array', function () {
    $item = ServiceAgendaItem::factory()->create([
        'responsible' => ['person1', 'person2'],
    ]);

    expect($item->responsible)->toBeArray();
    expect($item->responsible)->toHaveCount(2);
});

test('is_before_event is cast to boolean', function () {
    $item = ServiceAgendaItem::factory()->create(['is_before_event' => true]);

    expect($item->is_before_event)->toBeTrue();
    expect(is_bool($item->is_before_event))->toBeTrue();
});

test('unique constraint on service_id and sort_order', function () {
    $service = Service::factory()->create();
    ServiceAgendaItem::factory()->create([
        'service_id' => $service->id,
        'sort_order' => 1,
    ]);

    expect(fn () => ServiceAgendaItem::factory()->create([
        'service_id' => $service->id,
        'sort_order' => 1,
    ]))->toThrow(QueryException::class);
});

test('withSong factory state', function () {
    $song = ServiceSong::factory()->create();
    $item = ServiceAgendaItem::factory()->withSong($song)->create();

    expect($item->service_song_id)->toBe($song->id);
    expect($item->service_id)->toBe($song->service_id);
    expect($item->type)->toBe('Song');
});

test('nonSong factory state', function () {
    $item = ServiceAgendaItem::factory()->nonSong()->create();

    expect($item->service_song_id)->toBeNull();
    expect($item->type)->toBeIn(['Default', 'Header']);
});

test('cascadeOnDelete removes agenda items when service deleted', function () {
    $service = Service::factory()->create();
    ServiceAgendaItem::factory()->count(3)->create(['service_id' => $service->id]);

    expect(ServiceAgendaItem::where('service_id', $service->id)->count())->toBe(3);

    $service->delete();

    expect(ServiceAgendaItem::where('service_id', $service->id)->count())->toBe(0);
});

test('nullOnDelete nullifies service_song_id when song deleted', function () {
    $song = ServiceSong::factory()->create();
    $item = ServiceAgendaItem::factory()->create(['service_song_id' => $song->id]);

    expect($item->service_song_id)->toBe($song->id);

    $song->delete();
    $item->refresh();

    expect($item->service_song_id)->toBeNull();
});
