<?php

namespace App\Services;

use App\DAO\AdministrativoDAO;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\DAO\Filter\QueryFilter;
use App\DAO\Pagination\Pagination;
use App\Entities\Administrativo\Administrativo;
use App\Mappers\AdministrativoMapper;
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\Administrativo\AdministrativoDetailsViewModel\AdministrativoDetailsViewModel;
use App\ViewModels\Administrativo\AdministrativoRegistrationViewModel\AdministrativoRegistrationViewModel;

class AdministrativoService extends Service {

	public function getAdministrativo(QueryFilter $query_filter): ServiceResponse {

		$administrativo_dao = new AdministrativoDAO();
		$query_filter_collection = new QueryFilterCollection();
		$query_filter_collection->push( $query_filter );
		$dao_response = $administrativo_dao->getAdministrativo( $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) {
			$administrativo_details_vm = (function (AdministrativoDetailsViewModel $administrativo_details_vm): AdministrativoDetailsViewModel {
				return $administrativo_details_vm;
			})( $dao_response->getData() );
			$service_response->setData( $administrativo_details_vm->toArray() );
		}
		return $service_response;

	}

	public function registerAdministrativo(array $data): ServiceResponse {

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

			$administrativo_registration_vm = AdministrativoMapper::AdministrativoRegistrationViewModelMapper( $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 AdministrativoRegistrationViewModel', $response_exception->getData() );
			return ServiceResponse::builder()->setStatus( ServiceResponseInterface::SERVICE_INTERNAL_ERROR )
				->setErrors( $response_exception->getData() )
				->build();
		}
		$administrativo_dao = new AdministrativoDAO();
		$dao_response = $administrativo_dao->persistAdministrativoRegistrationVM( $administrativo_registration_vm,
			function () use ($administrativo_registration_vm, $passwd) {
				return $this->sendEmailConfirmationRegister( $administrativo_registration_vm, $passwd );
			} );
		$service_response = new ServiceResponse();
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				$administrativo = (function (Administrativo $administrativo): Administrativo {
					return $administrativo;
				})( $dao_response->getData() );

				$service_response->setData( [ 
					'id_administrativo' => $administrativo->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(AdministrativoRegistrationViewModel $administrativo_registration_vm, string $passwd): int {

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

	}

	public function administrativoAndMedicoAreLinked(int $id_medico, int $administrativo_uid): bool {

		$administrativo_dao = new AdministrativoDAO();
		$dao_response = $administrativo_dao->verifyAdministrativoAndMedicoAreLinked( $id_medico, $administrativo_uid );
		return $dao_response->getStatus() === DAOResponseInterface::SUCESS;

	}

	public function updateAdministrativoData(int $id_administrativo, array $data): ServiceResponse {

		try {
			$administrativo_update_vm = AdministrativoMapper::getAdministrativoUpdateVMFromArray( $data );
			if (count( $administrativo_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 AdministrativoUpdateViewModel', $response_exception->getData() );
			return ServiceResponse::builder()->setStatus( ServiceResponseInterface::SERVICE_INTERNAL_ERROR )
				->setErrors( $response_exception->getData() )
				->build();
		}

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

		$administrativo_dao = new AdministrativoDAO();
		$image = $administrativo_dao->getImageAdministrativo( $id_administrativo );
		$dao_response = $administrativo_dao->persistAdministrativoUpdateVM( $id_administrativo, $administrativo_update_vm );
		$service_response = new ServiceResponse();
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$this->updateClinicasByAdministrativo( $id_administrativo, $clinicas );
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				if (file_exists( $image ) === true) {
					unlink( $image );
				}
				break;
			case DAOResponseInterface::DUPLICATED_UNIQUE_KEY :
				if (file_exists( $administrativo_update_vm->getFoto() ) === true) {
					unlink( $administrativo_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( $administrativo_update_vm->getFoto() ) === true) {
					unlink( $administrativo_update_vm->getFoto() );
				}
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				if (file_exists( $administrativo_update_vm->getFoto() ) === true) {
					unlink( $administrativo_update_vm->getFoto() );
				}
				break;
		}
		return $service_response;

	}

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

		$administrativo_dao = new AdministrativoDAO();
		$dao_response = $administrativo_dao->getAdministrativoList( $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();
			$administrativo_details_array = AdministrativoMapper::getAdministrativoDetailsArrayFromAdministrativoDetailsVMList( $dao_response_data );
			$pagination = $dao_response->getPagination();
			$data = [ 
				'administrativos' => $administrativo_details_array,
				'pagination' => $pagination ? $pagination->toResponseArray() : null
			];
			$service_response->setData( $data );
		}
		return $service_response;

	}

	private function updateClinicasByAdministrativo(int $id_administrativo, array $data) {

		if (count( $data ) > 0) {
			$profissionalService = new ProfissionalService();
			$profissionalService_response = $profissionalService->getIdProfissionalByAdministrativoId( $id_administrativo );
			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] ) );
						}
					}
				}
			}
		}

	}

}