<?php

namespace App\Services;

use App\DAO\DAOResponse\DAOResponse;
use App\DAO\PetDAO;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\DAO\Filter\QueryFilter;
use App\DAO\Pagination\Pagination;
use App\Entities\Pet\Pet;
use App\Mappers\PetMapper;
use App\Services\JWT\UsuarioLogado;
use App\Services\ServiceResponse\ServiceResponse;
use App\Services\ServiceResponse\ServiceResponseInterface;
use App\Utils\Collections\QueryFilterCollection;
use App\Utils\Collections\QueryOrderCollection;
use App\Utils\ResponseException;
use App\ViewModels\Pet\PetDetailsViewModel\PetDetailsViewModel;
use App\ViewModels\Pet\PetRegistrationViewModel\PetRegistrationViewModel;

class PetService extends Service {

	public function getPet(QueryFilter $query_filter): ServiceResponse {

		$pet_dao = new PetDAO();
		$query_filter_collection = new QueryFilterCollection();
		$query_filter_collection->push( $query_filter );
		$dao_response = $pet_dao->getPet( $query_filter_collection );
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response_status = ServiceResponseInterface::SUCESS;
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$service_response_status = ServiceResponseInterface::RECORD_NOT_FOUND;
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response_status = ServiceResponseInterface::DATABASE_CONNECTION_ERROR;
				break;
		}
		$service_response = ServiceResponse::builder()->setStatus( $service_response_status )
			->build();
		if ($service_response_status === DAOResponseInterface::SUCESS) {
			$pet_details_vm = (function (PetDetailsViewModel $pet_details_vm): PetDetailsViewModel {
				return $pet_details_vm;
			})( $dao_response->getData() );
			$service_response->setData( $pet_details_vm->toArray() );
		}
		return $service_response;

	}

	public function getPetByClient(int $id_pet): ServiceResponse {

		// ID DO USUARIO
		$sql = '
            select
            cliente.id
            from usuario, cliente 
            where usuario.id_pessoa = cliente.id_pessoa
            AND usuario.id = :id_usuario:
        ';
		$binds = [ 
			'id_usuario' => UsuarioLogado::getUsuarioId()
		];
		$id_cliente = db_connect()->query( $sql, $binds )
			->getResultArray();

		$pet_dao = new PetDAO();
		$array_response = $pet_dao->getPetByClient( $id_pet, $id_cliente [0] ['id'] );

		$dao_response = new DAOResponse();

		if (count( $array_response ) > 0) {
			$dao_response->setStatus( DAOResponseInterface::SUCESS );
			$dao_response->setData( $array_response );
		} else {
			$dao_response->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
		}

		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response_status = ServiceResponseInterface::SUCESS;
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$service_response_status = ServiceResponseInterface::RECORD_NOT_FOUND;
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response_status = ServiceResponseInterface::DATABASE_CONNECTION_ERROR;
				break;
		}
		$service_response = ServiceResponse::builder()->setStatus( $service_response_status )
			->build();
		if ($service_response_status === DAOResponseInterface::SUCESS) {
			$service_response->setData( $dao_response->getData() );
		}
		return $service_response;

	}

	public function registerPet(array $data): ServiceResponse {

		try {
			$passwd = $this->generateRandomString( 10 );
			$data ['ativo'] = 1;

			if (isset( $_FILES ['foto'] )) {
				$ext = "." . pathinfo( $_FILES ['foto'] ['name'], PATHINFO_EXTENSION );
				// $ext = strtolower(substr($_FILES['foto']['name'], -4)); //Pegando extensão do arquivo
				$new_name = date( "Y.m.d-H.i.s" ) . $ext; // Definindo um novo nome para o arquivo
				$dir = '../writable/perfil/';
				move_uploaded_file( $_FILES ['foto'] ['tmp_name'], $dir . $new_name ); // Fazer upload do arquivo
				$data ['foto'] = $dir . $new_name;
			}

			$pet_registration_vm = PetMapper::PetRegistrationViewModelMapper( $data );
		} catch ( ResponseException $response_exception ) {
			$log_service = new LogService();
			$log_service->log_error( ServiceResponseInterface::SERVICE_INTERNAL_ERROR,
				'Ocorreu um erro durante o mapeamento da entidade PetRegistrationViewModel', $response_exception->getData() );
			return ServiceResponse::builder()->setStatus( ServiceResponseInterface::SERVICE_INTERNAL_ERROR )
				->setErrors( $response_exception->getData() )
				->build();
		}
		$pet_dao = new PetDAO();
		$dao_response = $pet_dao->persistPetRegistrationVM( $pet_registration_vm );
		$service_response = new ServiceResponse();

		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				$pet = (function (Pet $pet): Pet {
					return $pet;
				})( $dao_response->getData() );

				$service_response->setData( [ 
					'id_pet' => $pet->getId()
				] );
				break;
			case DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS :
				$service_response->setStatus( ServiceResponseInterface::FOREIGN_KEY_DONT_EXISTS );
				$service_response->setErrors( $dao_response->getErrors() );
				if (file_exists( $dir . $new_name ) === true) {
					unlink( $dir . $new_name );
				}
				break;
			case DAOResponseInterface::DUPLICATED_UNIQUE_KEY :
				$service_response->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
				$service_response->setErrors( $dao_response->getErrors() );
				if (file_exists( $dir . $new_name ) === true) {
					unlink( $dir . $new_name );
				}
				break;
			case DAOResponseInterface::INTERNAL_DAO_ERROR :
				$service_response->setStatus( ServiceResponseInterface::SERVICE_INTERNAL_ERROR );
				if (file_exists( $dir . $new_name ) === true) {
					unlink( $dir . $new_name );
				}
				break;
			default :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				if (file_exists( $dir . $new_name ) === true) {
					unlink( $dir . $new_name );
				}
				break;
		}
		return $service_response;

	}

	public function updatePetData(int $id_pet, array $data): ServiceResponse {

		try {
			$pet_update_vm = PetMapper::getPetUpdateVMFromArray( $data );
			if (count( $pet_update_vm->toArray( true ) ) === 0) {
				return ServiceResponse::builder()->setStatus( ServiceResponseInterface::INSUFFICIENT_DATA )
					->build();
			}
		} catch ( ResponseException $response_exception ) {
			$log_service = new LogService();
			$log_service->log_error( ServiceResponseInterface::SERVICE_INTERNAL_ERROR, 'Ocorreu um erro durante o mapeamento da entidade PetUpdateViewModel',
				$response_exception->getData() );
			return ServiceResponse::builder()->setStatus( ServiceResponseInterface::SERVICE_INTERNAL_ERROR )
				->setErrors( $response_exception->getData() )
				->build();
		}
		$pet_dao = new PetDAO();
		// $image = $pet_dao->getImagePet($id_pet);
		$dao_response = $pet_dao->persistPetUpdateVM( $id_pet, $pet_update_vm );
		$service_response = new ServiceResponse();
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				// if(file_exists($image) === true ){unlink($image);}
				break;
			case DAOResponseInterface::DUPLICATED_UNIQUE_KEY :
				if (file_exists( $pet_update_vm->getFoto() ) === true) {
					unlink( $pet_update_vm->getFoto() );
				}
				break;
			case DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS :
				$service_response->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
				$service_response->setErrors( $dao_response->getErrors() );
				if (file_exists( $pet_update_vm->getFoto() ) === true) {
					unlink( $pet_update_vm->getFoto() );
				}
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				if (file_exists( $pet_update_vm->getFoto() ) === true) {
					unlink( $pet_update_vm->getFoto() );
				}
				break;
		}
		return $service_response;

	}

	public function getPetList(?Pagination $pagination, ?QueryFilterCollection $query_filter_collection, ?QueryOrderCollection $query_order_collection = null): ServiceResponse {

		$pet_dao = new PetDAO();
		$dao_response = $pet_dao->getPetList( $pagination, $query_filter_collection, $query_order_collection );
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response_status = ServiceResponseInterface::SUCESS;
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$service_response_status = ServiceResponseInterface::RECORD_NOT_FOUND;
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response_status = ServiceResponseInterface::DATABASE_CONNECTION_ERROR;
				break;
		}
		$service_response = ServiceResponse::builder()->setStatus( $service_response_status )
			->build();
		if ($service_response_status === DAOResponseInterface::SUCESS) {
			$dao_response_data = $dao_response->getData();
			$pet_details_array = PetMapper::getPetDetailsArrayFromPetDetailsVMList( $dao_response_data );
			$pagination = $dao_response->getPagination();
			$data = [ 
				'pets' => $pet_details_array,
				'pagination' => $pagination ? $pagination->toResponseArray() : null
			];
			$service_response->setData( $data );
		}
		return $service_response;

	}

	public function getPetListByTutorId(?Pagination $pagination, ?QueryFilterCollection $query_filter_collection,
			?QueryOrderCollection $query_order_collection = null): ServiceResponse {

		$pet_dao = new PetDAO();
		$dao_response = $pet_dao->getPetListByTutorId( $pagination, $query_filter_collection, $query_order_collection );
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response_status = ServiceResponseInterface::SUCESS;
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$service_response_status = ServiceResponseInterface::RECORD_NOT_FOUND;
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response_status = ServiceResponseInterface::DATABASE_CONNECTION_ERROR;
				break;
		}
		$service_response = ServiceResponse::builder()->setStatus( $service_response_status )
			->build();
		if ($service_response_status === DAOResponseInterface::SUCESS) {
			$dao_response_data = $dao_response->getData();
			$pet_details_array = PetMapper::getPetDetailsArrayFromPetDetailsVMList( $dao_response_data );
			$pagination = $dao_response->getPagination();
			$data = [ 
				'pets' => $pet_details_array,
				'pagination' => $pagination ? $pagination->toResponseArray() : null
			];
			$service_response->setData( $data );
		}
		return $service_response;

	}

	public function getTutorIdsByPetId(int $idPet): ServiceResponse {

		$dao = new PetDAO();
		$service_response = new ServiceResponse();
		$daoResponse = $dao->getTutorIdsByPetId( $idPet );

		$service_response = $this->setServiceResponse( $daoResponse );

		return $service_response;

	}

	public function getDadosPetById(int $idPet): ServiceResponse {

		$service_response = new ServiceResponse();
		$dao = new PetDAO();

		$service_response = new ServiceResponse();
		$daoResponse = $dao->getDadosPetById( $idPet );

		$service_response = $this->setServiceResponse( $daoResponse );

		return $service_response;

	}

	public function getDadosCartaoVoucherByPetId(int $id_pet): ServiceResponse {

		$service_response = new ServiceResponse();

		$voucher_service = new VoucherService();

		$voucher_response = $voucher_service->getVoucherAtivosByPetId( $id_pet );

		$response = $this->getDadosCartaoMedicinaCCByPetId( $id_pet );

		if (($voucher_response->getStatus() != ServiceResponseInterface::DATABASE_CONNECTION_ERROR) &&
				($response->getStatus() != ServiceResponseInterface::DATABASE_CONNECTION_ERROR)) {

			if ($voucher_response->getStatus() == ServiceResponseInterface::RECORD_NOT_FOUND) {
				$service_response->setData( [ 
					'medicina_cc' => $response->getData(),
					'vouchers' => [ ]
				] );
			} else {
				$service_response->setData( [ 
					'medicina_cc' => $response->getData(),
					'vouchers' => $voucher_response->getData()
				] );
			}
			$service_response->setStatus( ServiceResponseInterface::SUCESS );
		} else {
			$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
			$service_response->setData( [ ] );
			$service_response->setErrors( [ 
				$response->getErrors(),
				$voucher_response->getErrors()
			] );
		}

		return $service_response;

	}

	public function getDadosCartaoMedicinaCCByPetId(int $id_pet): ServiceResponse {

		$service_response = new ServiceResponse();
		$dao = new PetDAO();

		$service_response = new ServiceResponse();
		$daoResponse = $dao->getDadosCartaoMedicinaCCByPetId( $id_pet );

		$service_response = $this->setServiceResponse( $daoResponse );

		return $service_response;

	}

}