<?php


namespace App\Services;

use App\DAO\AuthDAO;
use App\DAO\DAOResponse\DAOResponse;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\Entities\Usuario\Usuario;
use App\Mappers\ConfirmacaoEmailMapper;
use App\Services\ServiceResponse\ServiceResponse;
use App\Services\ServiceResponse\ServiceResponseInterface;
use App\Utils\DateUtils;
use Exception;

class AuthService extends Service {
	private $jwt_service;

	public function __construct() {

		$this->jwt_service = new JWTService();

	}

	public function confirmEmail(string $token): ServiceResponse {

		$auth_dao = new AuthDAO();
		$dao_response = $auth_dao->getConfirmacaoEmailByToken( $token );
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$confirmacao_email = ConfirmacaoEmailMapper::getConfirmacaoEmailFromDataArray( $dao_response->getData() );
				if ($confirmacao_email->getVerificado()) {
					$auth_service_status = ServiceResponseInterface::REQUEST_ALREADY_COMPLETED;
				} else {
					$creation_date = $confirmacao_email->getCriadoEm();
					$time_expiration = $confirmacao_email->getTempoExpiracao();
					$expiration_datetime = DateUtils::plus_minutes_to_datetime( $creation_date, $time_expiration * MINUTE );
					if ($expiration_datetime >= DateUtils::now()) {
						$dao_response = $auth_dao->confirmEmailByID( $confirmacao_email->getId() );
						$auth_service_status = $dao_response->getStatus() === DAOResponseInterface::SUCESS ? ServiceResponseInterface::SUCESS : ServiceResponseInterface::DATABASE_CONNECTION_ERROR;
					} else {
						$auth_service_status = ServiceResponseInterface::TOKEN_EXPIRED;
					}
				}
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$auth_service_status = ServiceResponseInterface::RECORD_NOT_FOUND;
				break;
			default :
				$auth_service_status = ServiceResponseInterface::SERVICE_INTERNAL_ERROR;
				break;
		}
		if ($auth_service_status === ServiceResponseInterface::DATABASE_CONNECTION_ERROR) {
			$log_service = new LogService();
			$log_service->log_error( $auth_service_status, 'Ocorre um erro desconhecido na camada de persistência no ato de confirmação do email.', [
					'token' => $token ] );
		}

		$urlFrontEnd = "http://vettree.prolins.com.br?confirmado=true";
		header( "location: $urlFrontEnd" );

		return ServiceResponse::builder()->setStatus( $auth_service_status )->build();

	}

	public function authenticatePaciente(string $email, string $passwd): ServiceResponse {

		return $this->authenticateUser( function () use ($email, $passwd): DAOResponse {
			$auth_dao = new AuthDAO();
			$dao_response = $auth_dao->authenticatePaciente( $email, $this->cript_password( $passwd ) );
			return $dao_response;
		}, PERFIL_PACIENTE );

	}

	public function authenticateAssistente(string $email, string $passwd): ServiceResponse {

		return $this->authenticateUser( function () use ($email, $passwd): DAOResponse {
			$auth_dao = new AuthDAO();
			$dao_response = $auth_dao->authenticateAssistente( $email, $this->cript_password( $passwd ) );
			return $dao_response;
		}, PERFIL_ASSISTENTE );

	}

	public function authenticateRecepcionista(string $email, string $passwd): ServiceResponse {

		return $this->authenticateUser( function () use ($email, $passwd): DAOResponse {
			$auth_dao = new AuthDAO();
			$dao_response = $auth_dao->authenticateRecepcionista( $email, $this->cript_password( $passwd ) );
			return $dao_response;
		}, PERFIL_RECEPCIONISTA );

	}

    public function authenticateAdministrativo(string $email, string $passwd): ServiceResponse {

        return $this->authenticateUser( function () use ($email, $passwd): DAOResponse {
            $auth_dao = new AuthDAO();
            $dao_response = $auth_dao->authenticateAdministrativo( $email, $this->cript_password( $passwd ) );
            return $dao_response;
        }, PERFIL_ASSISTENTE );

    }

	public function authenticateMedico(string $email, string $passwd): ServiceResponse {

		return $this->authenticateUser( function () use ($email, $passwd): DAOResponse {
			$auth_dao = new AuthDAO();
			$dao_response = $auth_dao->authenticateMedico( $email, $this->cript_password( $passwd ) );
			return $dao_response;
		}, PERFIL_MEDICO );

	}

	private function authenticateUser(callable $authenticate, int $profile): ServiceResponse {

		$dao_response = (function (DAOResponse $dao_response): DAOResponse {
			return $dao_response;
		})( $authenticate() );
		$response = new ServiceResponse();
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$user = (function (Usuario $user): Usuario {
					return $user;
				})( $dao_response->getData() );
				$permissoes = (new AuthDAO())->getPermissaoListByUsuarioId($user->getId());
				$user->setPermissoes($permissoes);
				$response->setStatus( ! ! $user->getEmailVerificadoEm() ? ServiceResponseInterface::SUCESS : ServiceResponseInterface::EMAIL_NOT_VERIFIED );
				$response->setData( [
						'id_usuario' => $user->getId(),
                        'id_perfil' => $user->getAlteradoPor(),
                        'descricao' => $user->getFoto(),
						'documento' => $dao_response->getData()->getDocumento(),
						'token' => $this->jwt_service->getSignedJWTForUser( $user, $profile ) ] );
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$response->setStatus( ServiceResponseInterface::UNAUTHORIZED );
				break;
			default :
				$response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
		}
		return $response;

	}

}
