<?php

declare(strict_types=1);

namespace Tests\Unit\Models;

use App\Models\User;
use Tests\TestCase;

class UserModelTest extends TestCase
{
    private User $userModel;

    protected function setUp(): void
    {
        parent::setUp();
        $this->userModel = new User();
    }

    public function testCreateUser(): void
    {
        $id = $this->userModel->createUser([
            'name' => 'Nuevo Usuario',
            'email' => 'nuevo@test.com',
            'password' => 'Secret123!',
            'role' => 'comercial_manager',
            'status' => 'active',
        ]);

        $this->assertIsInt($id);
        $this->assertGreaterThan(0, $id);

        $user = $this->userModel->findById($id);
        $this->assertNotNull($user);
        $this->assertEquals('nuevo@test.com', $user['email']);
        $this->assertEquals('comercial_manager', $user['role']);
    }

    public function testPasswordIsHashed(): void
    {
        $id = $this->userModel->createUser([
            'name' => 'Hash Test',
            'email' => 'hash@test.com',
            'password' => 'Secret123!',
            'role' => 'comercial_manager',
            'status' => 'active',
        ]);

        $user = $this->userModel->findById($id);
        $this->assertStringStartsWith('$2y$', $user['password']);
        $this->assertNotEquals('Secret123!', $user['password']);
    }

    public function testFindByEmail(): void
    {
        $this->userModel->createUser([
            'name' => 'Email User',
            'email' => 'email@test.com',
            'password' => 'Secret123!',
            'role' => 'comercial_manager',
            'status' => 'active',
        ]);

        $user = $this->userModel->findByEmail('email@test.com');
        $this->assertNotNull($user);
        $this->assertEquals('Email User', $user['name']);

        $notFound = $this->userModel->findByEmail('noexiste@test.com');
        $this->assertNull($notFound);
    }

    public function testVerifyPassword(): void
    {
        $id = $this->userModel->createUser([
            'name' => 'Verify Test',
            'email' => 'verify@test.com',
            'password' => 'CorrectPass1!',
            'role' => 'comercial_manager',
            'status' => 'active',
        ]);

        $user = $this->userModel->findById($id);

        $this->assertTrue($this->userModel->verifyPassword($user, 'CorrectPass1!'));
        $this->assertFalse($this->userModel->verifyPassword($user, 'WrongPass1!'));
    }

    public function testUpdatePassword(): void
    {
        $id = $this->userModel->createUser([
            'name' => 'Password User',
            'email' => 'passupdate@test.com',
            'password' => 'OldPass123!',
            'role' => 'comercial_manager',
            'status' => 'active',
        ]);

        $result = $this->userModel->updatePassword($id, 'NewPass456!');
        $this->assertTrue($result);

        $user = $this->userModel->findById($id);
        $this->assertTrue($this->userModel->verifyPassword($user, 'NewPass456!'));
        $this->assertFalse($this->userModel->verifyPassword($user, 'OldPass123!'));
    }

    public function testActivateUser(): void
    {
        $id = $this->userModel->createUser([
            'name' => 'Activate User',
            'email' => 'activate@test.com',
            'password' => 'Secret123!',
            'role' => 'comercial_manager',
            'status' => 'pending_activation',
        ]);

        $result = $this->userModel->activateUser($id);
        $this->assertTrue($result);

        $user = $this->userModel->findById($id);
        $this->assertEquals('active', $user['status']);
    }

    public function testFindByEmailOrFail(): void
    {
        $id = $this->userModel->createUser([
            'name' => 'Fail Test',
            'email' => 'failtest@test.com',
            'password' => 'Secret123!',
            'role' => 'comercial_manager',
            'status' => 'active',
        ]);

        $user = $this->userModel->findByEmailOrFail('failtest@test.com');
        $this->assertEquals($id, $user['id']);

        $this->expectException(\RuntimeException::class);
        $this->userModel->findByEmailOrFail('noexiste@test.com');
    }
}
