<?php


namespace App\Services;

use App\DAO\DAOResponse\DAOResponse;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\Services\ServiceResponse\ServiceResponse;
use App\Services\ServiceResponse\ServiceResponseInterface;
use App\Utils\Collections\GeneralCollection;
use App\Utils\ResponseException;
use CodeIgniter\Pager\Pager;
use Config\Services;
use Exception;

/**
 * Class Service
 *
 * @package App\Services
 */
class Service {

	/**
	 *
	 * @return string
	 */
	protected function generateToken(): string {

		$random_string = $this->generateRandomString( 40 );
		return md5( $random_string . time() );

	}

	/**
	 *
	 * @param int $length
	 * @return string
	 */
	protected function generateRandomString(int $length): string {

		$lower_case_chars = 'abcdefghijklmnopqrstuvwxyz';
		$upper_case_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
		$numbers = '0123456789';
		$chars = [ 
			$lower_case_chars,
			$upper_case_chars,
			$numbers,
			$special_chars
		];
		$passwd = '';
		for($i = 0; $i < $length; $i++) {
			$random_char_group = &$chars [rand( 0, 3 )];
			$passwd .= $random_char_group [rand( 0, strlen( $random_char_group ) - 1 )];
		}
		return $passwd;

	}

	/**
	 *
	 * @param string $password
	 * @return string
	 */
	protected function cript_password(string $password): string {

		return md5( $password );

	}

	/**
	 *
	 * @param int $id_medico
	 * @throws ResponseException
	 */
	protected function verifyMedicoPermissionForMedicoOperation(int $id_medico): void {

		$jwt_payload = JWTService::getTokenJWTPayload();
		if ($jwt_payload->getProfile() === PERFIL_MEDICO) {
			$id_medico_requester = (new MedicoService())->getMedicoIDFromUsuarioID( $jwt_payload->getUid() );
			if ($id_medico !== $id_medico_requester) {
				throw new ResponseException( [ 
					'id_medico_requester' => $id_medico_requester
				], 'Um médico tentou realizar uma operação envolvendo outro médico e foi impedido.' );
			}
		}

	}

	/**
	 *
	 * @param int $id_medico
	 * @throws ResponseException
	 */
	protected function verifyAssistentePermissionForMedicoOperation(int $id_medico): void {

		$jwt_payload = JWTService::getTokenJWTPayload();
		if ($jwt_payload->getProfile() === PERFIL_ASSISTENTE) {
			$assistente_and_medico_are_linked = (new AssistenteService())->assistenteAndMedicoAreLinked( $id_medico, $jwt_payload->getUid() );
			if (!$assistente_and_medico_are_linked) {
				throw new ResponseException( [ 
					'assistente_uid' => $jwt_payload->getUid()
				], 'Um assistente tentou realizar uma operação envolvendo um médico do qual não é assistente e foi impedido.' );
			}
		}

	}

	protected function getGeneralCollectionFromDAOResponse(DAOResponse $dao_response): GeneralCollection {

		return $dao_response->getData();

	}

	protected function setServiceResponse(DAOResponse $daoResponse): ServiceResponse {

		$response = new ServiceResponse();
		switch ($daoResponse->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$response->setStatus( ServiceResponseInterface::SUCESS );
				$response->setData( $daoResponse->getData() );
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$response->setStatus( ServiceResponseInterface::RECORD_NOT_FOUND );
				$response->setData( [ ] );
				break;
			case DAOResponseInterface::DUPLICATED_UNIQUE_KEY :
				$response->setStatus( ServiceResponseInterface::HAVE_CONFLICTS );
				$response->setData( [ ] );
				$response->setErrors( $daoResponse->getErrors() );
				break;
			case DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS :
				$response->setStatus( ServiceResponseInterface::FOREIGN_KEY_DONT_EXISTS );
				$response->setData( [ ] );
				$response->setErrors( $daoResponse->getErrors() );
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				$response->setData( [ ] );
				$response->setErrors( $daoResponse->getErrors() );
				break;
			case DAOResponseInterface::INSUFFICIENT_DATA :
				$response->setStatus( ServiceResponseInterface::INSUFFICIENT_DATA );
				$response->setData( [ ] );
				$response->setErrors( [ ] );
				break;
			default :
				$response->setStatus( ServiceResponseInterface::UNKNOWN_ERROR );
				$response->setData( $daoResponse->getData() ?? [ ]);
				$response->setErrors( $daoResponse->getErrors() );
				break;
		}

		return $response;

	}

}