<?php

use App\Models\Macro;
use App\Models\MacroAssignment;
use App\Models\Service;
use App\Models\ServiceMacroAssignment;
use App\Models\ServiceMacroOverride;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('override requires authentication', function () {
    $service = Service::factory()->create();
    $response = $this->post(route('services.macro-overrides.store', $service), ['part_type' => 'song']);
    $response->assertRedirect(route('login'));
});

test('store creates override and snapshots global assignments', function () {
    $user = User::factory()->create();
    $service = Service::factory()->create();
    $macro = Macro::factory()->create();
    MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macro->id, 'position' => 'all_slides', 'order' => 0]);
    MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macro->id, 'position' => 'first_slide', 'order' => 1]);

    $response = $this->actingAs($user)
        ->postJson(route('services.macro-overrides.store', $service), ['part_type' => 'song']);

    $response->assertStatus(200)->assertJson(['success' => true]);
    expect(ServiceMacroOverride::where('service_id', $service->id)->where('part_type', 'song')->exists())->toBeTrue();
    expect(ServiceMacroAssignment::where('service_id', $service->id)->count())->toBe(2);
});

test('store does not snapshot assignments from different part_type', function () {
    $user = User::factory()->create();
    $service = Service::factory()->create();
    $macro = Macro::factory()->create();
    MacroAssignment::create(['part_type' => 'song', 'macro_id' => $macro->id, 'position' => 'all_slides', 'order' => 0]);
    MacroAssignment::create(['part_type' => 'sermon', 'macro_id' => $macro->id, 'position' => 'all_slides', 'order' => 0]);

    $this->actingAs($user)
        ->postJson(route('services.macro-overrides.store', $service), ['part_type' => 'song']);

    expect(ServiceMacroAssignment::where('service_id', $service->id)->count())->toBe(1);
    expect(ServiceMacroAssignment::where('service_id', $service->id)->first()->part_type)->toBe('song');
});

test('destroy removes override and service-specific assignments', function () {
    $user = User::factory()->create();
    $service = Service::factory()->create();
    $macro = Macro::factory()->create();
    ServiceMacroOverride::create(['service_id' => $service->id, 'part_type' => 'song']);
    ServiceMacroAssignment::create([
        'service_id' => $service->id,
        'part_type' => 'song',
        'macro_id' => $macro->id,
        'position' => 'all_slides',
        'order' => 0,
    ]);

    $response = $this->actingAs($user)
        ->deleteJson(route('services.macro-overrides.destroy', $service), ['part_type' => 'song']);

    $response->assertStatus(200);
    expect(ServiceMacroOverride::where('service_id', $service->id)->count())->toBe(0);
    expect(ServiceMacroAssignment::where('service_id', $service->id)->count())->toBe(0);
});

test('storeAssignment creates service-level assignment', function () {
    $user = User::factory()->create();
    $service = Service::factory()->create();
    $macro = Macro::factory()->create();

    $response = $this->actingAs($user)
        ->postJson(route('services.macro-assignments.store', $service), [
            'part_type' => 'sermon',
            'macro_id' => $macro->id,
            'position' => 'last_slide',
            'order' => 0,
        ]);

    $response->assertStatus(200)->assertJson(['success' => true]);
    expect(ServiceMacroAssignment::count())->toBe(1);
    expect(ServiceMacroAssignment::first()->service_id)->toBe($service->id);
});

test('destroyAssignment removes service-level assignment', function () {
    $user = User::factory()->create();
    $service = Service::factory()->create();
    $macro = Macro::factory()->create();
    $assignment = ServiceMacroAssignment::create([
        'service_id' => $service->id,
        'part_type' => 'song',
        'macro_id' => $macro->id,
        'position' => 'all_slides',
        'order' => 0,
    ]);

    $response = $this->actingAs($user)
        ->deleteJson(route('services.macro-assignments.destroy', [$service, $assignment]));

    $response->assertStatus(200);
    expect(ServiceMacroAssignment::count())->toBe(0);
});
