<?php

use App\Enums\DeclarationStatus;
use App\Models\Declaration;
use Illuminate\Validation\ValidationException;

test('valid transition: created to en_cours', function () {
    $declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);

    $declaration->update(['status' => DeclarationStatus::EnCours]);

    expect($declaration->fresh()->status->value)->toBe('en_cours');
});

test('valid transition: en_cours to en_attente_client', function () {
    $declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
    $declaration->update(['status' => DeclarationStatus::EnCours]);

    $declaration->update(['status' => DeclarationStatus::EnAttenteClient]);

    expect($declaration->fresh()->status->value)->toBe('en_attente_client');
});

test('valid transition: en_attente_client to en_cours', function () {
    $declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
    $declaration->update(['status' => DeclarationStatus::EnCours]);
    $declaration->update(['status' => DeclarationStatus::EnAttenteClient]);

    $declaration->update(['status' => DeclarationStatus::EnCours]);

    expect($declaration->fresh()->status->value)->toBe('en_cours');
});

test('valid transition: en_cours to termine', function () {
    $declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
    $declaration->update(['status' => DeclarationStatus::EnCours]);

    $declaration->update(['status' => DeclarationStatus::Termine]);

    expect($declaration->fresh()->status->value)->toBe('termine');
});

test('valid transition: termine to ferme', function () {
    $declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
    $declaration->update(['status' => DeclarationStatus::EnCours]);
    $declaration->update(['status' => DeclarationStatus::Termine]);

    $declaration->update(['status' => DeclarationStatus::Ferme]);

    expect($declaration->fresh()->status->value)->toBe('ferme');
});

test('valid transition: en_attente_client to mise_en_demeure', function () {
    $declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
    $declaration->update(['status' => DeclarationStatus::EnCours]);
    $declaration->update(['status' => DeclarationStatus::EnAttenteClient]);

    $declaration->update(['status' => DeclarationStatus::MiseEnDemeure]);

    expect($declaration->fresh()->status->value)->toBe('mise_en_demeure');
});

test('valid transition: mise_en_demeure to en_cours', function () {
    $declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
    $declaration->update(['status' => DeclarationStatus::EnCours]);
    $declaration->update(['status' => DeclarationStatus::EnAttenteClient]);
    $declaration->update(['status' => DeclarationStatus::MiseEnDemeure]);

    $declaration->update(['status' => DeclarationStatus::EnCours]);

    expect($declaration->fresh()->status->value)->toBe('en_cours');
});

test('valid transition: mise_en_demeure to ferme', function () {
    $declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
    $declaration->update(['status' => DeclarationStatus::EnCours]);
    $declaration->update(['status' => DeclarationStatus::EnAttenteClient]);
    $declaration->update(['status' => DeclarationStatus::MiseEnDemeure]);

    $declaration->update(['status' => DeclarationStatus::Ferme]);

    expect($declaration->fresh()->status->value)->toBe('ferme');
});

test('invalid transition: created to ferme throws validation exception', function () {
    $declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);

    $declaration->update(['status' => DeclarationStatus::Ferme]);
})->throws(ValidationException::class);

test('invalid transition: created to termine throws validation exception', function () {
    $declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);

    $declaration->update(['status' => DeclarationStatus::Termine]);
})->throws(ValidationException::class);

test('auto-archive: ferme status sets archived_at', function () {
    $declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
    $declaration->update(['status' => DeclarationStatus::EnCours]);
    $declaration->update(['status' => DeclarationStatus::Termine]);

    expect($declaration->fresh()->archived_at)->toBeNull();

    $declaration->update(['status' => DeclarationStatus::Ferme]);

    $fresh = $declaration->fresh();
    expect($fresh->archived_at)->not->toBeNull();
});

test('scope active excludes archived declarations', function () {
    $active = Declaration::factory()->create([
        'status' => DeclarationStatus::Created,
        'archived_at' => null,
    ]);
    $archived = Declaration::factory()->create([
        'status' => DeclarationStatus::Created,
        'archived_at' => now(),
    ]);

    $activeIds = Declaration::active()->pluck('id')->all();

    expect($activeIds)->toContain($active->id);
    expect($activeIds)->not->toContain($archived->id);
});

test('scope archived includes only archived declarations', function () {
    $active = Declaration::factory()->create([
        'status' => DeclarationStatus::Created,
        'archived_at' => null,
    ]);
    $archived = Declaration::factory()->create([
        'status' => DeclarationStatus::Created,
        'archived_at' => now(),
    ]);

    $archivedIds = Declaration::archived()->pluck('id')->all();

    expect($archivedIds)->toContain($archived->id);
    expect($archivedIds)->not->toContain($active->id);
});
