<?php

namespace Tests\Feature;

use App\Models\BacklogItem;
use App\Models\Project;
use App\Models\User;
use App\Services\ResourceAccessService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class BacklogLifecycleTest extends TestCase
{
    use RefreshDatabase;

    private function authenticatedAdmin(): array
    {
        $user = User::factory()->create(['status' => 'active']);
        $this->grantAdminRole($user);

        return [$user, $user->createToken('backlog-test')->plainTextToken];
    }

    private function project(User $user): Project
    {
        return Project::create([
            'title' => 'پروژه بک‌لاگ',
            'project_manager_id' => $user->id,
            'created_by' => $user->id,
            'start_date' => now()->toDateString(),
            'end_date' => now()->addMonth()->toDateString(),
            'status' => 'in_progress',
        ]);
    }

    public function test_backlog_description_is_preserved_when_created_and_edited(): void
    {
        [$user, $token] = $this->authenticatedAdmin();
        $project = $this->project($user);

        $response = $this->withToken($token)->postJson('/api/backlog-items', [
            'title' => 'بک‌لاگ توضیح‌دار',
            'description' => 'توضیحات اولیه',
            'type' => 'feature',
            'project_id' => $project->id,
            'priority' => 'medium',
        ])->assertCreated()->assertJsonPath('data.description', 'توضیحات اولیه');

        $backlogId = $response->json('data.id');

        $this->withToken($token)->putJson("/api/backlog-items/{$backlogId}", [
            'title' => 'بک‌لاگ توضیح‌دار',
            'description' => 'توضیحات ویرایش‌شده',
            'type' => 'feature',
            'project_id' => $project->id,
            'priority' => 'medium',
        ])->assertOk()->assertJsonPath('data.description', 'توضیحات ویرایش‌شده');

        $this->assertDatabaseHas('backlog_items', [
            'id' => $backlogId,
            'description' => 'توضیحات ویرایش‌شده',
            'status' => 'active',
        ]);
    }

    public function test_conversion_assigns_task_and_archives_backlog_atomically(): void
    {
        [$admin, $token] = $this->authenticatedAdmin();
        $assignee = User::factory()->create(['status' => 'active']);
        $project = $this->project($admin);
        $backlog = BacklogItem::create([
            'title' => 'بک‌لاگ قابل تبدیل',
            'description' => 'شرح تسک',
            'type' => 'bug',
            'project_id' => $project->id,
            'priority' => 'high',
            'status' => 'active',
            'created_by' => $admin->id,
        ]);

        $response = $this->withToken($token)->postJson("/api/backlog-items/{$backlog->id}/convert-to-task", [
            'assignee_id' => $assignee->id,
            'priority' => 'urgent',
            'start_date' => now()->addDay()->toDateString(),
            'due_date' => now()->addDays(3)->toDateString(),
            'estimated_time' => 6,
        ])->assertCreated()->assertJsonPath('data.assignee_id', $assignee->id);

        $taskId = $response->json('data.id');
        $this->assertDatabaseHas('tasks', [
            'id' => $taskId,
            'assignee_id' => $assignee->id,
            'description' => 'شرح تسک',
            'priority' => 'urgent',
        ]);
        $this->assertDatabaseHas('backlog_items', [
            'id' => $backlog->id,
            'status' => 'converted',
            'converted_to_task_id' => $taskId,
        ]);
        $this->assertNotNull($backlog->fresh()->archived_at);
        $this->assertDatabaseHas('notifications', [
            'user_id' => $assignee->id,
            'type' => 'task_assigned',
            'notifiable_id' => $taskId,
        ]);
        $this->assertTrue(app(ResourceAccessService::class)->tasks($assignee)->whereKey($taskId)->exists());

        $this->withToken($token)->getJson('/api/backlog-items?archive_state=active')
            ->assertOk()->assertJsonCount(0, 'data');
        $this->withToken($token)->getJson('/api/backlog-items?archive_state=archived')
            ->assertOk()->assertJsonPath('data.0.converted_to_task_id', $taskId);

        $this->withToken($token)->postJson("/api/backlog-items/{$backlog->id}/convert-to-task", [
            'assignee_id' => $assignee->id,
            'priority' => 'high',
        ])->assertUnprocessable();
        $this->assertDatabaseCount('tasks', 1);
    }
}
