<?php

namespace Tests\Feature\Admin;

use App\Models\User;
use App\Support\Impersonation;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class AdminImpersonationTest extends TestCase
{
    use RefreshDatabase;

    public function test_admin_can_start_read_only_impersonation(): void
    {
        $admin = User::factory()->admin()->create();
        $investor = User::factory()->create([
            'first_name' => 'Ana',
            'last_name' => 'López',
        ]);

        $this->actingAs($admin)
            ->post(route('admin.users.impersonate.start', $investor))
            ->assertRedirect(route('dashboard'));

        $this->assertAuthenticatedAs($investor);
        $this->assertTrue(session(Impersonation::SESSION_READONLY));
        $this->assertSame($admin->id, session(Impersonation::SESSION_IMPERSONATOR_ID));
    }

    public function test_admin_cannot_impersonate_another_admin(): void
    {
        $admin = User::factory()->admin()->create();
        $otherAdmin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post(route('admin.users.impersonate.start', $otherAdmin))
            ->assertForbidden();

        $this->assertAuthenticatedAs($admin);
    }

    public function test_admin_cannot_impersonate_self(): void
    {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post(route('admin.users.impersonate.start', $admin))
            ->assertForbidden();
    }

    public function test_read_only_impersonation_blocks_mutating_requests(): void
    {
        $admin = User::factory()->admin()->create();
        $investor = User::factory()->create();

        $this->actingAs($admin)
            ->post(route('admin.users.impersonate.start', $investor));

        $this->patch(route('profile.update'), [
            'first_name' => $investor->first_name,
            'last_name' => 'Cambiado',
            'email' => $investor->email,
            'contact_number' => $investor->contact_number,
            'country' => $investor->country,
        ])
            ->assertRedirect();

        $this->assertSame(
            'Modo lectura: no puede realizar cambios mientras impersona a este usuario.',
            session('error'),
        );
    }

    public function test_admin_can_stop_impersonation_and_return_to_edit_page(): void
    {
        $admin = User::factory()->admin()->create();
        $investor = User::factory()->create();

        $this->actingAs($admin)
            ->post(route('admin.users.impersonate.start', $investor));

        $this->post(route('impersonation.stop'))
            ->assertRedirect(route('admin.users.edit', $investor));

        $this->assertAuthenticatedAs($admin);
        $this->assertFalse(session()->has(Impersonation::SESSION_IMPERSONATOR_ID));
    }

    public function test_blocked_user_can_be_impersonated_for_viewing(): void
    {
        $admin = User::factory()->admin()->create();
        $investor = User::factory()->create(['blocked_at' => now()]);

        $this->actingAs($admin)
            ->post(route('admin.users.impersonate.start', $investor))
            ->assertRedirect(route('dashboard'));

        $this->get(route('dashboard'))->assertOk();
    }
}
