<?php

namespace App\Services;

use App\ChameFacil\UsuarioServiceCF;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\DAO\Filter\QueryFilter;
use App\DAO\UsuarioDAO;
use App\Entities\Usuario\Usuario;
use App\Mappers\UsuarioMapper;
use App\Services\ServiceResponse\ServiceResponse;
use App\Services\ServiceResponse\ServiceResponseInterface;
use App\Utils\Collections\QueryFilterCollection;

// use phpDocumentor\Reflection\DocBlock\Tags\Var_;
class UsuarioService extends Service {

	public function changePassword(int $id_usuario, string $current_passwd, string $new_passwd): ServiceResponse {

		$service_response = new ServiceResponse();
		$jwt_payload = JWTService::getTokenJWTPayload();
		if ($id_usuario !== $jwt_payload->getUid()) { // O usuário solicitante só pode alterar a própria senha.
			$service_response->setStatus( ServiceResponseInterface::FORBIDDEN );
			return $service_response;
		}

		// apos validado
		$dao_response = (new UsuarioDAO())->changePassword( $id_usuario, $current_passwd, $new_passwd );

		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$service_response->setStatus( ServiceResponseInterface::RECORD_NOT_FOUND );
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
			default :
				$service_response->setStatus( ServiceResponseInterface::UNKNOWN_ERROR );
		}
		return $service_response;

		return $service_response;

	}

	public function forgetedPassword(string $email): ServiceResponse {

		$service_response = new ServiceResponse();

		$usuario_dao = new UsuarioDAO();
		$query_filter_collection = new QueryFilterCollection();
		/*
		 * $query_filter_collection->push(QueryFilter::builder()
		 * ->setTable('usuario')
		 * ->setNameParam('email')
		 * ->setValue($email)
		 * ->setIsExact(true)
		 * ->build());
		 * $query_filter_collection->push(QueryFilter::builder()
		 * ->setTable('usuario')
		 * ->setNameParam('ativo')
		 * ->setValue(1)
		 * ->setIsExact(true)
		 * ->build());
		 */
		$dao_response = $usuario_dao->getUsuarioByEmail( $email );
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$usuario = $dao_response->getData();
				$service_response->setStatus( $this->generatePasswd( $usuario_dao, $usuario ) );
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$service_response->setStatus( ServiceResponseInterface::RECORD_NOT_FOUND );
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
			default :
				$service_response->setStatus( ServiceResponseInterface::UNKNOWN_ERROR );
		}
		return $service_response;

	}

	private function performChangeUserPasswd(UsuarioDAO $usuario_dao, Usuario $usuario, string $current_passwd, string $new_passwd): int {

		if ($usuario->getSenha() === $this->cript_password( $current_passwd )) {
			$usuario->setSenha( $this->cript_password( $new_passwd ) );
			$dao_response = $usuario_dao->updateUsuarioPassword( $usuario );
			$service_response_status = [ 
				DAOResponseInterface::SUCESS => ServiceResponseInterface::SUCESS,
				DAOResponseInterface::DATABASE_CONNECTION_ERROR => ServiceResponseInterface::DATABASE_CONNECTION_ERROR
			] [$dao_response->getStatus()];
			return $service_response_status ?? DAOResponseInterface::UNKNOWN_ERROR;
		} else {
			return ServiceResponseInterface::UNAUTHORIZED;
		}

	}

	public function generateRandomString($length = 10): string {

		$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
		$charactersLength = strlen( $characters );
		$randomString = '';
		for($i = 0; $i < $length; $i++) {
			$randomString .= $characters [rand( 0, $charactersLength - 1 )];
		}
		return $randomString;

	}

	private function generatePasswd(UsuarioDAO $usuario_dao, Usuario $usuario): int {

		$new_passwd = $this->generateRandomString();

		$usuario_servce_cf = new UsuarioServiceCF();
		$usuario_chamefacil = new UsuarioDAO();
		$response_perfil_usuario = $usuario_chamefacil->getPerfilUsuario( $usuario->getId() );
		if ($response_perfil_usuario [0] ['id_perfil'] == 2) {
			$response_id_cf = $usuario_chamefacil->getIdChameFacilFromUsuario( $usuario->getId() );
			$response_usuario = $usuario_servce_cf->updateUsuarioCf( $usuario, $new_passwd, $response_id_cf [0] ['id_chamefacil'] );
		}

		$usuario->setSenha( $this->cript_password( $new_passwd ) );
		$dao_response = $usuario_dao->updateUsuarioPassword( $usuario );
		$service_response_status = [ 
			DAOResponseInterface::SUCESS => ServiceResponseInterface::SUCESS,
			DAOResponseInterface::DATABASE_CONNECTION_ERROR => ServiceResponseInterface::DATABASE_CONNECTION_ERROR
		] [$dao_response->getStatus()];
		if ($service_response_status) {
			$email_service_response = $this->sendEmailNewPasswd( $usuario->getEmail(), $new_passwd );
			return $email_service_response ?? ServiceResponseInterface::SERVICE_INTERNAL_ERROR;
		} else {
			return DAOResponseInterface::UNKNOWN_ERROR;
		}

	}

	private function sendEmailNewPasswd(string $email, string $passwd): int {

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

	}

	public function updateUserData(int $id_usuario, array $dataPost): ServiceResponse {

		$serviceResponse = new ServiceResponse();
		$jwtPayload = JWTService::getTokenJWTPayload();
		if ($jwtPayload->getUid() !== $id_usuario) {
			$serviceResponse->setStatus( ServiceResponseInterface::FORBIDDEN );
			return $serviceResponse;
		}
		$usuarioUpdateVM = UsuarioMapper::getUsuarioUpdateVMFromArray( $dataPost );

		$usuarioDAO = new UsuarioDAO();
		$dao_response = $usuarioDAO->persistUsuarioUpdateVM( $id_usuario, $usuarioUpdateVM );
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$serviceResponse->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
			case DAOResponseInterface::INTERNAL_DAO_ERROR :
				// Quando a camada DAO devolve erro interno, suporemos que é sempre erro de usuário não encontrado.
				// TODO: Posteriormente, essa validação deve ser mais precisa.
				$serviceResponse->setStatus( ServiceResponseInterface::RECORD_NOT_FOUND );
				break;
			case DAOResponseInterface::SUCESS :
				$serviceResponse->setStatus( ServiceResponseInterface::SUCESS );
				break;
			case DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS :
			case DAOResponseInterface::DUPLICATED_UNIQUE_KEY :
				$serviceResponse->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
				$serviceResponse->setErrors( $dao_response->getErrors() );
				break;
		}
		return $serviceResponse;

	}

	public function getUsuarioDataFromUsuarioIDRaw(int $id_usuario): ServiceResponse {

		$service_response = new ServiceResponse();
		$jwtPayload = JWTService::getTokenJWTPayload();
		if ($jwtPayload->getUid() !== $id_usuario) {
			$service_response->setStatus( ServiceResponseInterface::FORBIDDEN );
			return $service_response;
		}
		$usuario_dao = new UsuarioDAO();
		$dao_response = $usuario_dao->getUsuarioDadosFromUsuarioIDRaw( $id_usuario );
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				$service_response->setData( $dao_response->getData()
					->toArray() );
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$service_response->setStatus( ServiceResponseInterface::RECORD_NOT_FOUND );
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
		}
		return $service_response;

	}

	public function getUsuarioDataFromUsuarioID(int $id_usuario): ServiceResponse {

		$service_response = new ServiceResponse();
		$jwtPayload = JWTService::getTokenJWTPayload();
		if ($jwtPayload->getUid() !== $id_usuario) {
			$service_response->setStatus( ServiceResponseInterface::FORBIDDEN );
			return $service_response;
		}
		$usuario_dao = new UsuarioDAO();
		$dao_response = $usuario_dao->getUsuarioDadosFromUsuarioID( $id_usuario );
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				$service_response->setData( $dao_response->getData()
					->toArray() );
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$service_response->setStatus( ServiceResponseInterface::RECORD_NOT_FOUND );
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
		}
		return $service_response;

	}

	public function getMinhasUnidades(): ServiceResponse {

		$dao = new UsuarioDAO();
		$daoResponse = $dao->getMinhasUnidades();

		$service_response = new ServiceResponse();
		$service_response = $this->setServiceResponse( $daoResponse );
		return $service_response;

	}

	public function getDadosUsuarioByIdTolojacompra(int $id_usuario): ServiceResponse {

		$dao = new UsuarioDAO();
		$daoResponse = $dao->getDadosUsuarioByIdToLojaCompra( $id_usuario );

		$service_response = new ServiceResponse();
		$service_response = $this->setServiceResponse( $daoResponse );
		return $service_response;

	}

}
