<?php

namespace App\Services;

use App\ChameFacil\AuthBaseServiceCF;
use App\DAO\AssistenteDAO;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\DAO\Filter\QueryFilter;
use App\DAO\Pagination\Pagination;
use App\Entities\Assistente\Assistente;
use App\Mappers\AssistenteMapper;
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\Assistente\AssistenteDetailsViewModel\AssistenteDetailsViewModel;
use App\ViewModels\Assistente\AssistenteRegistrationViewModel\AssistenteRegistrationViewModel;
use GuzzleHttp\Client;
use App\DAO\DAOResponse\DAOResponse;

class AssistenteService extends Service {

	public function getAssistente(QueryFilter $query_filter): ServiceResponse {

		$assistente_dao = new AssistenteDAO();
		$query_filter_collection = new QueryFilterCollection();
		$query_filter_collection->push( $query_filter );
		$array_response = $assistente_dao->getMedicosFromAssistenteList( $query_filter->getValue() );
		$dao_response = $assistente_dao->getAssistente( $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) {
			$assistente_details_vm = (function (AssistenteDetailsViewModel $assistente_details_vm): AssistenteDetailsViewModel {
				return $assistente_details_vm;
			})( $dao_response->getData() );
			$assistente_details_vm->setMedicos( $array_response );
			$getIdUsuario_response = $assistente_dao->getUsuarioIdByAssistenteID( $assistente_details_vm->getId() );
			$data = $assistente_details_vm->toArray();
			$data ['id_usuario'] = $getIdUsuario_response->getData() ['id_usuario'];
			$unidade_service_response = (new UnidadeService())->getUnidadeListByUsuario( null, null, null, $data ['id_usuario'] );
			$data = array_merge( $data, $unidade_service_response->getData() );
			$service_response->setData( $data );
		}
		return $service_response;

	}

	public function registerAssistente(array $data): ServiceResponse {

		try {
			$passwd = $data ['senha'];
			$data ['senha_chamefacil'] = $data ['senha'];
			$data ['senha'] = $this->cript_password( $data ['senha'] );
			$data ['token_confirmacao_email'] = '';
			$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;
			}

			$assistente_registration_vm = AssistenteMapper::AssistenteRegistrationViewModelMapper( $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 AssistenteRegistrationViewModel', $response_exception->getData() );
			return ServiceResponse::builder()->setStatus( ServiceResponseInterface::SERVICE_INTERNAL_ERROR )
				->setErrors( $response_exception->getData() )
				->build();
		}
		$assistente_dao = new AssistenteDAO();
		$dao_response = $assistente_dao->persistAssistenteRegistrationVM( $assistente_registration_vm,
			function () use ($assistente_registration_vm, $passwd) {
				return $this->sendEmailConfirmationRegister( $assistente_registration_vm, $passwd );
			} );

		// Chame Facil
		$this->sendAssistenteChameFacil( $data );

		$service_response = new ServiceResponse();
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				$assistente = (function (Assistente $assistente): Assistente {
					return $assistente;
				})( $dao_response->getData() );

				$service_response->setData( [ 
					'id_assistente' => $assistente->getId()
				] );
				break;
			case DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS :
				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;

	}

	private function sendEmailConfirmationRegister(AssistenteRegistrationViewModel $assistente_registration_vm, string $passwd): int {

		$email_service = new EmailService();
		$data = [ 
			'senha' => $passwd,
			'email' => $assistente_registration_vm->getEmail()
		];
		$html_email = view( 'emails/assistente_registration', $data );
		$email_service_response = $email_service->send_email( $assistente_registration_vm->getEmail(), 'Confirmação de email', $html_email );
		return $email_service_response->getStatus() === ServiceResponseInterface::SUCESS ? ServiceResponseInterface::SUCESS : ServiceResponseInterface::SERVICE_INTERNAL_ERROR;

	}

	public function assistenteAndMedicoAreLinked(int $id_medico, int $assistente_uid): bool {

		$assistente_dao = new AssistenteDAO();
		$dao_response = $assistente_dao->verifyAssistenteAndMedicoAreLinked( $id_medico, $assistente_uid );
		return $dao_response->getStatus() === DAOResponseInterface::SUCESS;

	}

	public function updateAssistenteData(int $id_assistente, array $data): ServiceResponse {

		try {
			$assistente_update_vm = AssistenteMapper::getAssistenteUpdateVMFromArray( $data );
			if (count( $assistente_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 AssistenteUpdateViewModel', $response_exception->getData() );
			return ServiceResponse::builder()->setStatus( ServiceResponseInterface::SERVICE_INTERNAL_ERROR )
				->setErrors( $response_exception->getData() )
				->build();
		}

		$unidades = $data ['unidades'];
		$clinicas = array_unique( explode( ",", $unidades ) );

		$assistente_dao = new AssistenteDAO();
		$image = $assistente_dao->getImageAssistente( $id_assistente );
		$dao_response = $assistente_dao->persistAssistenteUpdateVM( $id_assistente, $assistente_update_vm );
		$service_response = new ServiceResponse();
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$this->updateClinicasByAssistente( $id_assistente, $clinicas );
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				if (file_exists( $image ) === true) {
					unlink( $image );
				}
				break;
			case DAOResponseInterface::DUPLICATED_UNIQUE_KEY :
				if (file_exists( $assistente_update_vm->getFoto() ) === true) {
					unlink( $assistente_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( $assistente_update_vm->getFoto() ) === true) {
					unlink( $assistente_update_vm->getFoto() );
				}
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				if (file_exists( $assistente_update_vm->getFoto() ) === true) {
					unlink( $assistente_update_vm->getFoto() );
				}
				break;
		}
		return $service_response;

	}

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

		$assistente_dao = new AssistenteDAO();
		$dao_response = $assistente_dao->getAssistenteList( $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();
			$assistente_details_array = AssistenteMapper::getAssistenteDetailsArrayFromAssistenteDetailsVMList( $dao_response_data );
			$pagination = $dao_response->getPagination();
			$data = [ 
				'assistentes' => $assistente_details_array,
				'pagination' => $pagination ? $pagination->toResponseArray() : null
			];
			$service_response->setData( $data );
		}
		return $service_response;

	}

	private function sendAssistenteChameFacil(array $recepcionista) {

		$auth_chamefacil = new AuthBaseServiceCF();
		$credenciais_chamefacil = $auth_chamefacil->authBaseService();

		$client = new Client();
		$result = $client->post( 'http://chamefacilpettree.prolins.com.br/api/usuario/Adicionar',
			[ 
				'headers' => [ 
					'token' => $credenciais_chamefacil->Token
				],
				'json' => [ 
					"Codigo" => 0,
					"Nome" => $recepcionista ['nome'],
					"Login" => $recepcionista ['email'],
					"Senha" => $recepcionista ['senha_chamefacil'],
					"CodigoPerfil" => 2,
					"Cadastro" => date( 'Y-m-d H:i:s' ),
					"Ativo" => 1,
					"Email" => $recepcionista ['email'],
					"TokenPushRequest" => ""
				]
			] );
		return $result->getBody()
			->getContents();

	}

	public function getAssistenteIDFromUsuarioID(int $id_usuario): int {

		$dao = new AssistenteDAO();
		$dao_response = $dao->getAssistenteIDFromUsuarioID( $id_usuario );
		$id_assistente = $dao_response->getStatus() === DAOResponseInterface::SUCESS ? ( int ) $dao_response->getData() : 0;
		return $id_assistente;

	}

	public function getUsuarioIDFromAssitenteID(int $id_assistente): ServiceResponse {

		$dao = new AssistenteDAO();
		$daoResponse = $dao->getUsuarioIDFromAssitenteID( $id_assistente );
		$service_response = new ServiceResponse();
		$service_response = $this->setServiceResponse( $daoResponse );

		return $service_response;

	}

	public function getAssistenteByUnidadeID(int $id_unidade): ServiceResponse {

		$dao = new AssistenteDAO();
		$daoResponse = $dao->getAssistenteByUnidadeID( $id_unidade );
		$service_response = new ServiceResponse();
		$service_response = $this->setServiceResponse( $daoResponse );

		return $service_response;

	}

	private function updateClinicasByAssistente(int $id_assistente, array $data) {

		if (count( $data ) > 0) {
			$profissionalService = new ProfissionalService();
			$profissionalService_response = $profissionalService->getIdProfissionalByAssistenteId( $id_assistente );
			if ($profissionalService_response->getStatus() == ServiceResponseInterface::SUCESS) {
				$dados = $profissionalService_response->getData();
				$idProfissional = $dados [0] ['id_profissional'];
				$profissionalClienicaService = new ProfissionalClinicaService();
				$profissionalClienicaService_response = $profissionalClienicaService->getClinicasByProfissionalId( $idProfissional );
				if ($profissionalClienicaService_response->getStatus() == ServiceResponseInterface::SUCESS) {
					$resposta = $profissionalClienicaService_response->getData();
					$minhas_clinicas = array ();
					for($y = 0; $y < count( $resposta ); $y++) {
						array_push( $minhas_clinicas, $resposta [$y] ['is_unidade'] );
					}
					// alterar estrutura de minhas clinicas.
					$excluir = array_values( array_diff( $minhas_clinicas, array_values( $data ) ) );
					$incluir = array_values( array_diff( array_values( $data ), $minhas_clinicas ) );

					for($i = 0; $i < count( $incluir ); $i++) {
						if (intval( $incluir [$i] ) > 0) {
							$incluir_response = $profissionalClienicaService->incluirProfissionalClinica( $idProfissional, intval( $incluir [$i] ) );
						}
					}

					for($i = 0; $i < count( $excluir ); $i++) {
						if (intval( $excluir [$i] ) > 0) {
							$excluir_response = $profissionalClienicaService->excluirProfissionalClinica( $idProfissional, intval( $excluir [$i] ) );
						}
					}
				}
				if ($profissionalClienicaService_response->getStatus() == ServiceResponseInterface::RECORD_NOT_FOUND) {

					for($i = 0; $i < count( $data ); $i++) {
						if (intval( $data [$i] ) > 0) {
							$incluir_response = $profissionalClienicaService->incluirProfissionalClinica( $idProfissional, intval( $data [$i] ) );
						}
					}
				}
			}
		}

	}

}