<?php

namespace Tests\Unit\Customer;

use Tests\TestCase;
use Mockery;
use Exception;
use App\Models\Customer;
use App\Services\Customer\CustomerService;
use App\Http\Requests\Customer\AddCustomerRequest;
use App\Http\Requests\Customer\EditCustomerRequest;
use App\Http\Controllers\Customer\CustomerController;
use Illuminate\Foundation\Testing\RefreshDatabase;

class CustomerControllerTest extends TestCase
{
    use RefreshDatabase;

    public function test_register_customer_success()
    {
        // Crear un mock de AddCustomerRequest
        $requestMock = Mockery::mock(AddCustomerRequest::class);
        $requestMock->shouldReceive('validated')->andReturn([
            'name' => 'John Doe',
            'phone' => '77049267',
            'email' => 'johndoe@example.com',
            'gender' => 'M',
            'ci' => 123456789,
            'cod_phone' => '+591',
            'date_of_birthday' => '1990-01-01',
            'adress' => '123 Main St',
        ]);

        // Crear un mock de CustomerService
        $customerServiceMock = Mockery::mock(CustomerService::class);
        $customerServiceMock->shouldReceive('createCustomer')->andReturn(new Customer([
            'name' => 'John Doe',
            'phone' => '77049267',
            'email' => 'johndoe@example.com',
            'gender' => 'M',
            'ci' => 123456789,
            'cod_phone' => '+591',
            'date_of_birthday' => '1990-01-01',
            'adress' => '123 Main St',
        ]));

        // Instanciar el controlador con el mock del servicio
        $controller = new CustomerController($customerServiceMock);

        // Ejecutar el método register_customer
        $response = $controller->register_customer($requestMock);

        // Afirmar que la respuesta es 201 y contiene los datos correctos
        $this->assertEquals(201, $response->status());
        $this->assertArrayHasKey('data', $response->getData(true));
        $this->assertEquals('John Doe', $response->getData(true)['data']['name']);
    }

    public function test_register_customer_failure()
    {
        // Crear un mock de AddCustomerRequest
        $requestMock = Mockery::mock(AddCustomerRequest::class);
        $requestMock->shouldReceive('validated')->andThrow(new Exception('Validation error'));

        // Crear un mock de CustomerService
        $customerServiceMock = Mockery::mock(CustomerService::class);

        // Instanciar el controlador con el mock del servicio
        $controller = new CustomerController($customerServiceMock);

        // Ejecutar el método register_customer y capturar la excepción
        $response = $controller->register_customer($requestMock);

        // Afirmar que la respuesta es 500
        $this->assertEquals(500, $response->status());
    }

    public function test_update_customer_success()
    {
        // Crear un mock de EditCustomerRequest
        $requestMock = Mockery::mock(EditCustomerRequest::class);
        $requestMock->shouldReceive('validated')->andReturn([
            'name' => 'Jane Doe',
            'phone' => '78049267',
            'email' => 'janedoe@example.com',
            'gender' => 'F',
            'ci' => 987654321,
            'cod_phone' => '+591',
            'date_of_birthday' => '1991-02-01',
            'adress' => '456 Main St',
        ]);

        // Crear un mock de CustomerService
        $customerServiceMock = Mockery::mock(CustomerService::class);
        $customerServiceMock->shouldReceive('updateCustomer')->andReturn(new Customer([
            'name' => 'Jane Doe',
            'phone' => '78049267',
            'email' => 'janedoe@example.com',
            'gender' => 'F',
            'ci' => 987654321,
            'cod_phone' => '+591',
            'date_of_birthday' => '1991-02-01',
            'adress' => '456 Main St',
        ]));

        // Instanciar el controlador con el mock del servicio
        $controller = new CustomerController($customerServiceMock);

        // Ejecutar el método update_customer
        $response = $controller->update_customer(1, $requestMock);

        // Afirmar que la respuesta es 200 y contiene los datos correctos
        $this->assertEquals(200, $response->status());
        $this->assertArrayHasKey('data', $response->getData(true));
        $this->assertEquals('Jane Doe', $response->getData(true)['data']['name']);
    }

    public function test_update_customer_failure()
    {
        // Crear un mock de EditCustomerRequest
        $requestMock = Mockery::mock(EditCustomerRequest::class);
        $requestMock->shouldReceive('validated')->andThrow(new Exception('Validation error'));

        // Crear un mock de CustomerService
        $customerServiceMock = Mockery::mock(CustomerService::class);

        // Instanciar el controlador con el mock del servicio
        $controller = new CustomerController($customerServiceMock);

        // Ejecutar el método update_customer y capturar la excepción
        $response = $controller->update_customer(1, $requestMock);

        // Afirmar que la respuesta es 500
        $this->assertEquals(500, $response->status());
    }
}
