<?php

namespace Tests\Feature;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class AuthTest extends TestCase
{
    use RefreshDatabase;

    public function test_login_returns_token_with_valid_credentials(): void
    {
        $user = User::factory()->create([
            'email' => 'test@example.com',
            'password' => bcrypt('password'),
            'allow_login' => true,
        ]);

        $response = $this->postJson('/api/auth/login', [
            'email' => 'test@example.com',
            'password' => 'password',
        ]);

        $response->assertOk();
        $response->assertJsonStructure(['user', 'token', 'token_type']);
        $response->assertJsonPath('user.email', 'test@example.com');
    }

    public function test_login_fails_with_invalid_credentials(): void
    {
        $response = $this->postJson('/api/auth/login', [
            'email' => 'wrong@example.com',
            'password' => 'wrong',
        ]);

        $response->assertStatus(422);
    }

    public function test_authenticated_user_can_get_profile(): void
    {
        $user = User::factory()->create();
        $token = $user->createToken('api')->plainTextToken;

        $response = $this->withHeader('Authorization', 'Bearer ' . $token)
            ->getJson('/api/auth/user');

        $response->assertOk();
        $response->assertJsonPath('id', $user->id);
    }

    public function test_re_login_revokes_existing_api_token_by_default(): void
    {
        $user = User::factory()->create([
            'email' => 'test@example.com',
            'password' => bcrypt('password'),
            'allow_login' => true,
        ]);

        $firstToken = $user->createToken('api')->plainTextToken;

        $this->postJson('/api/auth/login', [
            'email' => 'test@example.com',
            'password' => 'password',
        ])->assertOk();

        $this->withHeader('Authorization', 'Bearer '.$firstToken)
            ->getJson('/api/auth/user')
            ->assertUnauthorized();
    }

    public function test_re_login_keeps_existing_token_when_revoke_disabled(): void
    {
        config(['hrms_auth.api_revoke_tokens_on_login' => false]);

        $user = User::factory()->create([
            'email' => 'keep@example.com',
            'password' => bcrypt('password'),
            'allow_login' => true,
        ]);

        $firstToken = $user->createToken('api')->plainTextToken;

        $this->postJson('/api/auth/login', [
            'email' => 'keep@example.com',
            'password' => 'password',
        ])->assertOk();

        $this->withHeader('Authorization', 'Bearer '.$firstToken)
            ->getJson('/api/auth/user')
            ->assertOk();
    }

    public function test_logout_revokes_current_token_only(): void
    {
        $user = User::factory()->create([
            'allow_login' => true,
        ]);

        $token = $user->createToken('api')->plainTextToken;

        $this->withHeader('Authorization', 'Bearer '.$token)
            ->postJson('/api/auth/logout')
            ->assertOk();

        $this->withHeader('Authorization', 'Bearer '.$token)
            ->getJson('/api/auth/user')
            ->assertUnauthorized();
    }

    public function test_inactive_user_login_is_rejected(): void
    {
        User::factory()->create([
            'email' => 'inactive@example.com',
            'password' => bcrypt('password'),
            'allow_login' => true,
            'status' => User::STATUS_INACTIVE,
        ]);

        $response = $this->postJson('/api/auth/login', [
            'email' => 'inactive@example.com',
            'password' => 'password',
        ]);

        $response->assertStatus(422);
        $response->assertJsonPath('errors.email.0', 'Please contact the administrator.');
        $this->assertArrayNotHasKey('token', $response->json());
    }

    public function test_delete_account_soft_deactivates_and_revokes_tokens(): void
    {
        $user = User::factory()->create([
            'allow_login' => true,
            'status' => User::STATUS_ACTIVE,
        ]);
        $token = $user->createToken('api')->plainTextToken;

        $this->withHeader('Authorization', 'Bearer '.$token)
            ->postJson('/api/auth/delete-account')
            ->assertOk()
            ->assertJsonPath('message', 'Account deactivated successfully.');

        $this->assertSame(User::STATUS_INACTIVE, $user->fresh()->status);

        $this->withHeader('Authorization', 'Bearer '.$token)
            ->getJson('/api/auth/user')
            ->assertUnauthorized();
    }

    public function test_delete_account_when_already_inactive_is_idempotent(): void
    {
        $user = User::factory()->create([
            'allow_login' => true,
            'status' => User::STATUS_INACTIVE,
        ]);
        $token = $user->createToken('api')->plainTextToken;

        $this->withHeader('Authorization', 'Bearer '.$token)
            ->postJson('/api/auth/delete-account')
            ->assertOk()
            ->assertJsonPath('message', 'Account is already inactive.');

        $this->assertSame(User::STATUS_INACTIVE, $user->fresh()->status);
    }

    public function test_reactivated_user_can_login_again(): void
    {
        $user = User::factory()->create([
            'email' => 'reactivate@example.com',
            'password' => bcrypt('password'),
            'allow_login' => true,
            'status' => User::STATUS_INACTIVE,
        ]);

        $this->postJson('/api/auth/login', [
            'email' => 'reactivate@example.com',
            'password' => 'password',
        ])->assertStatus(422);

        $user->forceFill(['status' => User::STATUS_ACTIVE])->save();

        $this->postJson('/api/auth/login', [
            'email' => 'reactivate@example.com',
            'password' => 'password',
        ])
            ->assertOk()
            ->assertJsonStructure(['user', 'token', 'token_type']);
    }
}
