<?php

use App\Enums\NocTrackingStatus;
use App\Enums\WorkAssignmentStatus;
use App\Enums\WorkInternalStatus;
use App\Models\File;
use App\Models\Role;
use App\Models\User;
use App\Models\Work;
use App\Models\WorkAssignment;
use App\Services\Works\WorkOperationsService;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

test('applyTechnicianClosure persiste clareo y estado interno', function () {
    $work = createWorkWithUserAssignments();

    app(WorkOperationsService::class)->applyTechnicianClosure(
        $work,
        '2026-05-10T14:30',
        WorkInternalStatus::FINALIZADO->value,
    );

    $work->refresh();
    expect($work->internal_status)->toBe(WorkInternalStatus::FINALIZADO->value);
    expect($work->clearance_datetime)->not->toBeNull();
});

test('applyTechnicianClosure agrega filas de bitácora al pasar a finalizado u observado', function () {
    $coord = createUserWithRole(Role::COORDINATOR_NAME);
    $tech = createUserWithRole(Role::TECHNICIAN_NAME);
    $work = createWorkWithUserAssignments(technician: $tech, coordinator: $coord);
    $work->update(['internal_status' => WorkInternalStatus::PENDIENTE->value]);

    WorkAssignment::query()->create([
        'work_id' => $work->id,
        'technician_id' => $tech->id,
        'coordinator_id' => $coord->id,
        'recorded_at' => now()->subHour(),
        'status' => WorkAssignmentStatus::ASIGNADO->value,
    ]);

    app(WorkOperationsService::class)->applyTechnicianClosure(
        $work,
        '2026-05-10T14:30',
        WorkInternalStatus::FINALIZADO->value,
    );

    expect(WorkAssignment::query()->where('work_id', $work->id)->count())->toBe(2);
    $last = WorkAssignment::query()->where('work_id', $work->id)->orderByDesc('recorded_at')->orderByDesc('id')->first();
    expect($last->status)->toBe(WorkAssignmentStatus::FINALIZADO->value);

    app(WorkOperationsService::class)->applyTechnicianClosure(
        $work->fresh(),
        '2026-05-10T15:00',
        WorkInternalStatus::OBSERVADO->value,
    );

    expect(WorkAssignment::query()->where('work_id', $work->id)->count())->toBe(3);
    $last = WorkAssignment::query()->where('work_id', $work->id)->orderByDesc('recorded_at')->orderByDesc('id')->first();
    expect($last->status)->toBe(WorkAssignmentStatus::OBSERVADO->value);
});

test('applyNocTracking persiste estado, comentario y usuario NOC', function () {
    $work = createWorkWithUserAssignments();
    $actor = User::factory()->create();

    app(WorkOperationsService::class)->applyNocTracking(
        $work,
        NocTrackingStatus::CERRADO->value,
        'Listo',
        $actor->id,
    );

    $work->refresh();
    expect($work->noc_tracking_status)->toBe(NocTrackingStatus::CERRADO->value);
    expect($work->noc_comment)->toBe('Listo');
    expect((int) $work->noc_id)->toBe((int) $actor->id);
});

test('storeAttachmentsFromUploads guarda en disco public y registra file', function () {
    Storage::fake(Work::WORK_FILES_DISK);

    $uploader = User::factory()->create();
    $work = createWorkWithUserAssignments();
    $pdf = UploadedFile::fake()->create('informe.pdf', 120, 'application/pdf');

    app(WorkOperationsService::class)->storeAttachmentsFromUploads($work, [$pdf], $uploader->id);

    $row = File::query()->where('work_id', $work->id)->first();
    expect($row)->not->toBeNull();
    expect($row->disk)->toBe(Work::WORK_FILES_DISK);
    expect($row->uploaded_by_user_id)->toBe($uploader->id);
    Storage::disk(Work::WORK_FILES_DISK)->assertExists($row->path);
});

test('deleteAttachment elimina registro y objeto en storage', function () {
    Storage::fake(Work::WORK_FILES_DISK);

    $work = createWorkWithUserAssignments();
    $path = 'work-files/'.$work->id.'/test.pdf';
    Storage::disk(Work::WORK_FILES_DISK)->put($path, 'fake');

    $file = File::query()->create([
        'disk' => Work::WORK_FILES_DISK,
        'path' => $path,
        'name' => 'test.pdf',
        'mime_type' => 'application/pdf',
        'size_bytes' => 4,
        'work_id' => $work->id,
        'uploaded_by_user_id' => User::factory()->create()->id,
    ]);

    app(WorkOperationsService::class)->deleteAttachment($file);

    expect(File::query()->find($file->id))->toBeNull();
    Storage::disk(Work::WORK_FILES_DISK)->assertMissing($path);
});
