<?php

use App\Models\Action;
use App\Models\Client;
use App\Models\ClientCase;
use App\Models\Contract;
use App\Models\Decision;
use App\Models\FieldJob;
use App\Models\FieldJobSetting;
use App\Models\Segment;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

it('completes field job and moves contract to return segment when end_field_job event fires', function () {
    // Auth user
    $user = User::factory()->create();
    $this->actingAs($user);

    // Minimal person/client/case
    $person = \App\Models\Person\Person::factory()->create([
        'first_name' => 'Job',
        'last_name' => 'Runner',
        'full_name' => 'Job Runner',
    ]);
    $client = Client::create(['person_id' => $person->id]);
    $case = ClientCase::create([
        'client_id' => $client->id,
        'person_id' => $person->id,
    ]);

    $returnSeg = Segment::factory()->create(['name' => 'Return']);
    $fieldSeg = Segment::factory()->create(['name' => 'Field']);

    $action = Action::create(['name' => 'Call', 'color_tag' => '#000', 'segment_id' => $returnSeg->id]);
    $decision = Decision::create(['name' => 'Finish field job', 'color_tag' => '#00f', 'auto_mail' => false]);
    $action->decisions()->attach($decision->id);

    // Create a contract under the case and attach field segment as active
    $contract = Contract::create([
        'reference' => 'REF-2002',
        'client_case_id' => $case->id,
        'type_id' => \Database\Factories\ContractTypeFactory::new()->create()->id,
        'start_date' => now()->toDateString(),
    ]);
    // Ensure both segments exist on the case and contract
    DB::table('client_case_segment')->insert([
        ['client_case_id' => $case->id, 'segment_id' => $fieldSeg->id, 'active' => true, 'created_at' => now(), 'updated_at' => now()],
        ['client_case_id' => $case->id, 'segment_id' => $returnSeg->id, 'active' => true, 'created_at' => now(), 'updated_at' => now()],
    ]);
    DB::table('contract_segment')->insert([
        ['contract_id' => $contract->id, 'segment_id' => $fieldSeg->id, 'active' => true, 'created_at' => now(), 'updated_at' => now()],
        ['contract_id' => $contract->id, 'segment_id' => $returnSeg->id, 'active' => false, 'created_at' => now(), 'updated_at' => now()],
    ]);

    // FieldJobSetting with return segment
    $setting = FieldJobSetting::create([
        'segment_id' => $fieldSeg->id,
        'assign_decision_id' => $decision->id, // not used here
        'complete_decision_id' => $decision->id,
        'return_segment_id' => $returnSeg->id,
        'queue_segment_id' => $fieldSeg->id,
        'action_id' => $action->id,
    ]);

    // Active FieldJob for this contract (simulates assignment)
    FieldJob::create([
        'field_job_setting_id' => $setting->id,
        'assigned_user_id' => $user->id,
        'contract_id' => $contract->id,
        'assigned_at' => now()->subDay(),
    ]);

    // Insert end_field_job event (satisfy legacy options NOT NULL)
    $eventId = DB::table('events')->insertGetId([
        'name' => 'End Field Job',
        'key' => 'end_field_job',
        'description' => 'Complete a field job',
        'active' => true,
        'options' => json_encode(new stdClass),
        'config' => json_encode(new stdClass),
        'created_at' => now(),
        'updated_at' => now(),
    ]);

    DB::table('decision_event')->insert([
        'decision_id' => $decision->id,
        'event_id' => $eventId,
        'active' => true,
        'run_order' => 1,
        'config' => json_encode([]),
        'created_at' => now(),
        'updated_at' => now(),
    ]);

    // Spy on logs to assert EndFieldJob ran
    Log::spy();

    $this->post(route('clientCase.activity.store', $case), [
        'action_id' => $action->id,
        'decision_id' => $decision->id,
        'contract_uuid' => $contract->uuid,
        'note' => 'Finish job',
    ])->assertSessionHasNoErrors();

    // The active field job should be marked completed
    $completedJob = FieldJob::query()
        ->where('contract_id', $contract->id)
        ->latest('id')
        ->first();

    expect($completedJob)->not()->toBeNull();
    expect($completedJob->completed_at)->not()->toBeNull();

    // The contract should now be in return segment
    $activeSegIds = DB::table('contract_segment')
        ->where('contract_id', $contract->id)
        ->where('active', true)
        ->pluck('segment_id');

    expect($activeSegIds->contains($returnSeg->id))->toBeTrue();
});
