<?php

namespace Tests\Feature\Customer;

use App\Enums\UserStatus;
use App\Enums\UserType;
use App\Models\User;
use App\Services\Settings\SettingService;
use App\Support\InstallationState;
use App\Support\UserAccess;
use Database\Seeders\RoleAndPermissionSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\File;
use Tests\TestCase;

class CustomerStatusTest extends TestCase
{
    use RefreshDatabase;

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

        File::put(app(InstallationState::class)->lockPath(), now()->toIso8601String());
        $this->seed(RoleAndPermissionSeeder::class);
    }

    public function test_deactivated_customer_cannot_log_in(): void
    {
        $customer = $this->createCustomer(UserStatus::Suspended);

        $this->post(route('login'), [
            'email' => $customer->email,
            'password' => 'password',
        ])
            ->assertRedirect(route('login'))
            ->assertSessionHas('error');

        $this->assertGuest();
    }

    public function test_admin_can_deactivate_customer_from_staff_list(): void
    {
        $admin = $this->createAdmin();
        $customer = $this->createCustomer(UserStatus::Active);

        $this->actingAs($admin)
            ->patch(route('customers.status', $customer), [
                'status' => UserStatus::Suspended->value,
            ])
            ->assertRedirect(route('staff.index', ['tab' => 'customers']))
            ->assertSessionHas('status');

        $customer->refresh();
        $this->assertTrue($customer->isSuspended());
    }

    public function test_admin_can_reactivate_customer(): void
    {
        $admin = $this->createAdmin();
        $customer = $this->createCustomer(UserStatus::Suspended);

        $this->actingAs($admin)
            ->patch(route('customers.status', $customer), [
                'status' => UserStatus::Active->value,
            ])
            ->assertRedirect(route('staff.index', ['tab' => 'customers']))
            ->assertSessionHas('status');

        $customer->refresh();
        $this->assertTrue($customer->isActive());
    }

    public function test_deactivated_customer_is_logged_out_on_next_request(): void
    {
        $customer = $this->createCustomer(UserStatus::Active);

        $this->actingAs($customer)
            ->get(route('customer.home'))
            ->assertOk();

        $customer->update(['status' => UserStatus::Suspended]);

        $this->actingAs($customer->fresh())
            ->get(route('customer.home'))
            ->assertRedirect(route('login'))
            ->assertSessionHas('error');
    }

    public function test_admin_can_deactivate_customer_from_edit_form(): void
    {
        $admin = $this->createAdmin();
        $customer = $this->createCustomer(UserStatus::Active);

        $this->actingAs($admin)
            ->put(route('customers.update', $customer), [
                'name' => $customer->name,
                'email' => $customer->email,
                'status' => UserStatus::Suspended->value,
            ])
            ->assertRedirect(route('staff.index', ['tab' => 'customers']));

        $customer->refresh();
        $this->assertTrue($customer->isSuspended());
    }

    private function createAdmin(): User
    {
        $admin = User::factory()->create([
            'user_type' => UserType::Staff,
        ]);
        $admin->assignRole('Super Admin');

        return $admin;
    }

    private function createCustomer(UserStatus $status): User
    {
        $customer = User::factory()->create([
            'user_type' => UserType::Customer,
            'status' => $status,
        ]);
        $customer->assignRole(UserAccess::customerRoleName());

        return $customer;
    }
}
