<?php

namespace Tests\Feature\TeamMember;

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 TeamMemberTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
    }

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

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

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

    // 2.1.9 API test: POST /api/team-members creates member
    public function test_post_team_members_creates_member()
    {
        $token = $this->loginAsManager();
        $role = Role::factory()->create(['name' => 'Backend Developer']);

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->postJson('/api/team-members', [
                'name' => 'John Doe',
                'role_id' => $role->id,
                'hourly_rate' => 150.00,
                'active' => true,
            ]);

        $response->assertStatus(201);
        $response->assertJson([
            'data' => [
                'name' => 'John Doe',
                'hourly_rate' => '150.00',
                'active' => true,
            ],
        ]);
        $response->assertJsonPath('data.role.id', $role->id);

        $this->assertDatabaseHas('team_members', [
            'name' => 'John Doe',
            'role_id' => $role->id,
            'active' => true,
        ]);
    }

    // 2.1.10 API test: Validate hourly_rate > 0
    public function test_validate_hourly_rate_must_be_greater_than_zero()
    {
        $token = $this->loginAsManager();
        $role = Role::factory()->create(['name' => 'Backend Developer']);

        // Test with zero
        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->postJson('/api/team-members', [
                'name' => 'John Doe',
                'role_id' => $role->id,
                'hourly_rate' => 0,
            ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['hourly_rate']);

        // Test with negative
        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->postJson('/api/team-members', [
                'name' => 'John Doe',
                'role_id' => $role->id,
                'hourly_rate' => -50,
            ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['hourly_rate']);
        $response->assertJsonFragment([
            'hourly_rate' => ['Hourly rate must be greater than 0'],
        ]);
    }

    // 2.1.11 API test: Validate required fields
    public function test_validate_required_fields()
    {
        $token = $this->loginAsManager();

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->postJson('/api/team-members', []);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['name', 'role_id', 'hourly_rate']);
    }

    // 2.1.12 API test: GET /api/team-members returns all members
    public function test_get_team_members_returns_all_members()
    {
        $token = $this->loginAsManager();
        $role = Role::factory()->create();

        // Create active and inactive team members
        TeamMember::factory()->count(2)->create(['role_id' => $role->id, 'active' => true]);
        TeamMember::factory()->create(['role_id' => $role->id, 'active' => false]);

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->getJson('/api/team-members');

        $response->assertStatus(200);
        $response->assertJsonCount(3, 'data');
    }

    // 2.1.13 API test: Filter by active status
    public function test_filter_by_active_status()
    {
        $token = $this->loginAsManager();
        $role = Role::factory()->create();

        // Create active and inactive team members
        TeamMember::factory()->count(2)->create(['role_id' => $role->id, 'active' => true]);
        TeamMember::factory()->create(['role_id' => $role->id, 'active' => false]);

        // Get only active
        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->getJson('/api/team-members?active=true');

        $response->assertStatus(200);
        $response->assertJsonCount(2, 'data');

        // Get only inactive
        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->getJson('/api/team-members?active=false');

        $response->assertStatus(200);
        $response->assertJsonCount(1, 'data');
    }

    // 2.1.14 API test: PUT /api/team-members/{id} updates member
    public function test_put_team_members_updates_member()
    {
        $token = $this->loginAsManager();
        $role = Role::factory()->create();
        $teamMember = TeamMember::factory()->create([
            'role_id' => $role->id,
            'hourly_rate' => 150.00,
        ]);

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->putJson("/api/team-members/{$teamMember->id}", [
                'hourly_rate' => 175.00,
            ]);

        $response->assertStatus(200);
        $response->assertJson([
            'data' => [
                'id' => $teamMember->id,
                'hourly_rate' => '175.00',
            ],
        ]);

        $this->assertDatabaseHas('team_members', [
            'id' => $teamMember->id,
            'hourly_rate' => '175.00',
        ]);
    }

    // 2.1.15 API test: Deactivate sets active=false
    public function test_deactivate_sets_active_to_false()
    {
        $token = $this->loginAsManager();
        $role = Role::factory()->create();
        $teamMember = TeamMember::factory()->create([
            'role_id' => $role->id,
            'active' => true,
        ]);

        $response = $this->withHeader('Authorization', "Bearer {$token}")
            ->putJson("/api/team-members/{$teamMember->id}", [
                'active' => false,
            ]);

        $response->assertStatus(200);
        $response->assertJson([
            'data' => [
                'id' => $teamMember->id,
                'active' => false,
            ],
        ]);

        $this->assertDatabaseHas('team_members', [
            'id' => $teamMember->id,
            'active' => false,
        ]);
    }

    // 2.1.16 API test: DELETE rejected if allocations exist
    public function test_delete_rejected_if_allocations_exist()
    {
        $token = $this->loginAsManager();
        $role = Role::factory()->create();
        $teamMember = TeamMember::factory()->create(['role_id' => $role->id]);
        $project = Project::factory()->create();

        // Create an allocation for the team member
        Allocation::factory()->create([
            'team_member_id' => $teamMember->id,
            'project_id' => $project->id,
            'month' => '2024-01',
            'allocated_hours' => 40,
        ]);

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

        $response->assertStatus(422);
        $response->assertJson([
            'message' => 'Cannot delete team member with active allocations',
            'suggestion' => 'Consider deactivating the team member instead',
        ]);

        // Verify the team member still exists
        $this->assertDatabaseHas('team_members', [
            'id' => $teamMember->id,
        ]);
    }

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

        $this->withHeader('Authorization', "Bearer {$token}")
            ->getJson('/api/team-members?active=true')
            ->assertStatus(200)
            ->assertJsonCount(1, 'data');

        $this->withHeader('Authorization', "Bearer {$token}")
            ->putJson("/api/team-members/{$teamMember->id}", [
                'active' => false,
            ])
            ->assertStatus(200);

        $this->withHeader('Authorization', "Bearer {$token}")
            ->getJson('/api/team-members?active=true')
            ->assertStatus(200)
            ->assertJsonCount(0, 'data');

        $this->withHeader('Authorization', "Bearer {$token}")
            ->getJson('/api/team-members?active=false')
            ->assertStatus(200)
            ->assertJsonCount(1, 'data');
    }
}
