<?php

namespace Tests\Feature;

use App\Models\Allocation;
use App\Models\Project;
use App\Models\Role;
use App\Models\TeamMember;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class AllocationTest extends TestCase
{
    use RefreshDatabase;

    protected function loginAsManager()
    {
        $user = User::factory()->create([
            'email' => 'manager@test.com',
            'password' => bcrypt('password123'),
            'role' => 'manager',
            'active' => true,
        ]);

        $response = $this->postJson('/api/auth/login', [
            'email' => 'manager@test.com',
            'password' => 'password123',
        ]);

        return $response->json('access_token');
    }

    public function test_post_allocations_creates_allocation(): void
    {
        $token = $this->loginAsManager();
        $project = Project::factory()->create();
        $role = Role::factory()->create();
        $teamMember = TeamMember::factory()->create(['role_id' => $role->id, 'active' => true]);

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->postJson('/api/allocations', [
                'project_id' => $project->id,
                'team_member_id' => $teamMember->id,
                'month' => '2026-02',
                'allocated_hours' => 40,
            ]);

        $response->assertStatus(201);
        $this->assertDatabaseHas('allocations', [
            'project_id' => $project->id,
            'allocated_hours' => 40,
        ]);
    }

    public function test_validate_hours_must_be_greater_than_zero(): void
    {
        $token = $this->loginAsManager();
        $project = Project::factory()->create();
        $role = Role::factory()->create();
        $teamMember = TeamMember::factory()->create(['role_id' => $role->id, 'active' => true]);

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->postJson('/api/allocations', [
                'project_id' => $project->id,
                'team_member_id' => $teamMember->id,
                'month' => '2026-02',
                'allocated_hours' => -10,
            ]);

        $response->assertStatus(422);
    }

    public function test_get_allocations_returns_matrix(): void
    {
        $token = $this->loginAsManager();
        $project = Project::factory()->create();
        $role = Role::factory()->create();
        $teamMember = TeamMember::factory()->create(['role_id' => $role->id, 'active' => true]);

        Allocation::factory()->create([
            'project_id' => $project->id,
            'team_member_id' => $teamMember->id,
            'month' => '2026-02-01',
            'allocated_hours' => 40,
        ]);

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->getJson('/api/allocations?month=2026-02');

        $response->assertStatus(200);
    }

    public function test_put_allocations_updates(): void
    {
        $token = $this->loginAsManager();
        $allocation = Allocation::factory()->create();

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->putJson("/api/allocations/{$allocation->id}", [
                'allocated_hours' => 50,
            ]);

        $response->assertStatus(200);
        $this->assertDatabaseHas('allocations', [
            'id' => $allocation->id,
            'allocated_hours' => 50,
        ]);
    }

    public function test_delete_allocation_removes(): void
    {
        $token = $this->loginAsManager();
        $allocation = Allocation::factory()->create();

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->deleteJson("/api/allocations/{$allocation->id}");

        $response->assertStatus(200);
        $this->assertDatabaseMissing('allocations', [
            'id' => $allocation->id,
        ]);
    }

    public function test_post_allocations_bulk_creates_multiple(): void
    {
        $token = $this->loginAsManager();
        $project = Project::factory()->create();
        $role = Role::factory()->create();
        $teamMember = TeamMember::factory()->create(['role_id' => $role->id, 'active' => true]);

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->postJson('/api/allocations/bulk', [
                'allocations' => [
                    [
                        'project_id' => $project->id,
                        'team_member_id' => $teamMember->id,
                        'month' => '2026-02',
                        'allocated_hours' => 40,
                    ],
                ],
            ]);

        $response->assertStatus(201);
        $this->assertDatabaseCount('allocations', 1);
    }

    public function test_allocate_zero_hours_is_allowed(): void
    {
        $token = $this->loginAsManager();
        $project = Project::factory()->create();
        $role = Role::factory()->create();
        $teamMember = TeamMember::factory()->create(['role_id' => $role->id, 'active' => true]);

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->postJson('/api/allocations', [
                'project_id' => $project->id,
                'team_member_id' => $teamMember->id,
                'month' => '2026-02',
                'allocated_hours' => 0,
            ]);

        $response->assertStatus(201);
    }

    public function test_cannot_update_nonexistent_allocation(): void
    {
        $token = $this->loginAsManager();
        $fakeId = '550e8400-e29b-41d4-a716-446655440000';

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->putJson("/api/allocations/{$fakeId}", [
                'allocated_hours' => 50,
            ]);

        $response->assertStatus(404);
    }

    public function test_cannot_delete_nonexistent_allocation(): void
    {
        $token = $this->loginAsManager();
        $fakeId = '550e8400-e29b-41d4-a716-446655440000';

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->deleteJson("/api/allocations/{$fakeId}");

        $response->assertStatus(404);
    }
}
