<?php

namespace App\Services;

use App\DAO\UnidadeDAO;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\DAO\Filter\QueryFilter;
use App\DAO\Pagination\Pagination;
use App\Mappers\UnidadeMapper;
use App\Mappers\UnidadeUFMapper;
use App\Services\ServiceResponse\ServiceResponse;
use App\Services\ServiceResponse\ServiceResponseInterface;
use App\Utils\ResponseException;
use App\Utils\Collections\QueryFilterCollection;
use App\Utils\Collections\QueryOrderCollection;
use App\ViewModels\Unidade\UnidadeDetailsViewModel\UnidadeDetailsViewModel;
//use const False\MyClass\true;

class UnidadeService extends Service {

	public function getUnidade(QueryFilter $query_filter): ServiceResponse {

		$unidade_dao = new UnidadeDAO();
		$query_filter_collection = new QueryFilterCollection();
		$query_filter_collection->push( $query_filter );
		$dao_response = $unidade_dao->getUnidade( $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) {
			$unidade_details_vm = (function (UnidadeDetailsViewModel $unidade_details_vm): UnidadeDetailsViewModel {
				return $unidade_details_vm;
			})( $dao_response->getData() );
			$service_response->setData( $unidade_details_vm->toArray() );
		}
		return $service_response;

	}

	public function registerUnidade(array $data): ServiceResponse {

		try {
			$unidade_registration_vm = UnidadeMapper::UnidadeRegistrationViewModelMapper( $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 UnidadeRegistrationViewModel', $response_exception->getData() );
			return ServiceResponse::builder()->setStatus( ServiceResponseInterface::SERVICE_INTERNAL_ERROR )
				->setErrors( $response_exception->getData() )
				->build();
		}
		$unidade_dao = new UnidadeDAO();
		$dao_response = $unidade_dao->persistUnidadeRegistrationVM( $unidade_registration_vm );
		$service_response = new ServiceResponse();
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				break;
			case DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS :
				$service_response->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
				$service_response->setErrors( $dao_response->getErrors() );
				break;
			case DAOResponseInterface::DUPLICATED_UNIQUE_KEY :
				$service_response->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
				$service_response->setErrors( $dao_response->getErrors() );
				break;
			case DAOResponseInterface::INTERNAL_DAO_ERROR :
				$service_response->setStatus( ServiceResponseInterface::SERVICE_INTERNAL_ERROR );
				break;
			default :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
		}
		return $service_response;

	}

	public function updateUnidadeData(int $id_unidade, $id_pessoa_juridica, array $data): ServiceResponse {

		try {
			$unidade_update_vm = UnidadeMapper::getUnidadeUpdateVMFromArray( $data );
			if (count( $unidade_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 UnidadeUpdateViewModel',
				$response_exception->getData() );
			return ServiceResponse::builder()->setStatus( ServiceResponseInterface::SERVICE_INTERNAL_ERROR )
				->setErrors( $response_exception->getData() )
				->build();
		}
		$unidade_dao = new UnidadeDAO();
		$dao_response = $unidade_dao->persistUnidadeUpdateVM( $id_unidade, $id_pessoa_juridica, $unidade_update_vm );
		$service_response = new ServiceResponse();
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				break;
			case DAOResponseInterface::DUPLICATED_UNIQUE_KEY :
				$service_response->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
				$service_response->setErrors( $dao_response->getErrors() );
				break;
			case DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS :
				$service_response->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
				$service_response->setErrors( $dao_response->getErrors() );
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
		}
		return $service_response;

	}

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

		$unidade_dao = new UnidadeDAO();
		$dao_response = $unidade_dao->getUnidadeList( $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();
			$unidade_details_array = UnidadeMapper::getUnidadeDetailsArrayFromUnidadeDetailsVMList( $dao_response_data );
			$pagination = $dao_response->getPagination();
			$data = [ 
				'unidades' => $unidade_details_array,
				'pagination' => $pagination ? $pagination->toResponseArray() : null
			];
			$service_response->setData( $data );
		}
		return $service_response;

	}

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

		$unidade_dao = new UnidadeDAO();
		$dao_response = $unidade_dao->getUnidadeListByUsuario( $pagination, $query_filter_collection, $query_order_collection, $id_usuario );
		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();
			$unidade_details_array = UnidadeMapper::getUnidadeDetailsArrayFromUnidadeDetailsVMList( $dao_response_data );
			$pagination = $dao_response->getPagination();
			$data = [ 
				'unidades' => $unidade_details_array,
				'pagination' => $pagination ? $pagination->toResponseArray() : null
			];
			$service_response->setData( $data );
		}
		return $service_response;

	}

	public function getDadosUnidadeById(int $id_unidade): ServiceResponse {

		$unidade_dao = new UnidadeDAO();
		$dao_response = $unidade_dao->getDadosUnidadeFromId( $id_unidade );
		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();
			$data = [ 
				'unidade' => $dao_response_data
			];
			$service_response->setData( $data );
		}
		return $service_response;

	}

	public function getUnidadesToUsuarioId(int $usuarioid): ServiceResponse {

		$unidade_dao = new UnidadeDAO();
		$dao_response = $unidade_dao->getUnidadesToUsuarioId( $usuarioid );
		$service_response_status = ServiceResponseInterface::UNKNOWN_ERROR;

		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();
			$data = [ 
				'unidades' => $dao_response_data
			];
			$service_response->setData( $data );
		}
		return $service_response;

	}

	public function getListUnidadeFisicasAllUF(): ServiceResponse {

		$serice_response = new ServiceResponse();
		$dao = new UnidadeDAO();
		$daoResponse = $dao->getListUnidadeFisicasAllUF();

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

		return $serice_response;

	}

	public function registerUnidadeUF(array $dados): ServiceResponse {

		$service_response = new ServiceResponse();

		$objregister = UnidadeUFMapper::getUnidadeUFRegistrationVMFromArray( $dados );

		$dao = new UnidadeDAO();
		$daoResponse = $dao->persistUnidadeUF( $objregister );

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

		return $service_response;

	}

	public function updateUnidadeUF(array $dados): ServiceResponse {

		$service_response = new ServiceResponse();

		$objregister = UnidadeUFMapper::getUnidadeUFUpdateVMFromArray( $dados );

		$dao = new UnidadeDAO();
		$daoResponse = $dao->updateUnidadeUF( $objregister );

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

		return $service_response;

	}

	public function getListUFWithUnidadesFisicas(): ServiceResponse {

		$service_response = new ServiceResponse();

		$dao = new UnidadeDAO();
		$daoResponse = $dao->getListUfWithUnidadesFisicas();

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

		return $service_response;

	}

	public function getListUnidadeFisicaByUF(int $uf): ServiceResponse {

		$service_response = new ServiceResponse();

		$dao = new UnidadeDAO();
		$daoResponse = $dao->getListUnidadeFisicaByUF( $uf );

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

		return $service_response;

	}

	public function getListUF(): ServiceResponse {

		$service_response = new ServiceResponse();

		$dao = new UnidadeDAO();
		$daoResponse = $dao->getListUF();

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

		return $service_response;

	}

	public function getListUnidadesAllUF(Pagination $pagination): ServiceResponse {

		$service_response = new ServiceResponse();

		$dao = new UnidadeDAO();
		$daoResponse = $dao->getListUnidadesAllUF( $pagination );

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

		return $service_response;

	}
	
	public function changeStatusByUnidadeId(int $id_unidade, int $status) {
		
		$service_response = new ServiceResponse();
		
		$dao = new UnidadeDAO();
		$daoResponse = $dao->changeStatusByUnidadeId( $id_unidade, $status );
		
		$service_response = $this->setServiceResponse( $daoResponse );
		
		return $service_response;
		
	}
	
	
	public function getUnidadesAtivasList(?Pagination $pagination, ?QueryFilterCollection $query_filter_collection,
			?QueryOrderCollection $query_order_collection = null): ServiceResponse {
				
				$unidade_dao = new UnidadeDAO();
				$dao_response = $unidade_dao->getUnidadesAtivasList( $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();
					$unidade_details_array = UnidadeMapper::getUnidadeDetailsArrayFromUnidadeDetailsVMList( $dao_response_data );
					$pagination = $dao_response->getPagination();
					$data = [
							'unidades' => $unidade_details_array,
							'pagination' => $pagination ? $pagination->toResponseArray() : null
					];
					$service_response->setData( $data );
				}
				return $service_response;
				
	}

}
