<?php

namespace App\DAO;

use App\DAO\DAOResponse\DAOResponse;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\Entities\Usuario\Usuario;
use App\Mappers\UsuarioMapper;
use App\Services\LogService;

class AuthDAO extends DAO {

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

		$sql = "
            SELECT
                usuario.id as id,
                email_verificado_em,
                usuario_perfil.id_perfil,
                perfil.descricao
            FROM usuario, pessoa, paciente, usuario_perfil, perfil
            WHERE
                usuario.id_pessoa = pessoa.id AND
                usuario_perfil.id_usuario = usuario.id AND
                perfil.id = usuario_perfil.id_perfil AND
                pessoa.id = paciente.id_pessoa AND 
                usuario.email = :email: AND
                usuario.senha = :passwd: AND
        	    usuario.ativo = 1
            LIMIT 1
        ";
		return $this->authenticateUser( $email, $passwd, $sql );

	}

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

		$sql = "
            SELECT
                usuario.id as id,
                email_verificado_em,
                usuario_perfil.id_perfil,
                perfil.descricao,
				medico.documento
            FROM usuario, pessoa, profissional, medico, usuario_perfil, perfil
            WHERE
                usuario.id_pessoa = pessoa.id AND
                usuario_perfil.id_usuario = usuario.id AND
                perfil.id = usuario_perfil.id_perfil AND
                pessoa.id = profissional.id_pessoa AND
                medico.id_profissional = profissional.id AND
                usuario.email = :email: AND
                usuario.senha = :passwd: AND
        	    usuario.ativo = 1
            LIMIT 1
        ";
		return $this->authenticateUser( $email, $passwd, $sql );

	}

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

		$sql = "
            SELECT
                usuario.id as id,
                email_verificado_em,
                usuario_perfil.id_perfil,
                perfil.descricao,
				assistente.documento
            FROM usuario, pessoa, profissional, assistente, usuario_perfil, perfil
            WHERE
                usuario.id_pessoa = pessoa.id AND
                usuario_perfil.id_usuario = usuario.id AND
                perfil.id = usuario_perfil.id_perfil AND
                pessoa.id = profissional.id_pessoa AND
                assistente.id_profissional = profissional.id AND
                usuario.email = :email: AND
                usuario.senha = :passwd: AND
        	    usuario.ativo = 1
            LIMIT 1
        ";
		return $this->authenticateUser( $email, $passwd, $sql );

	}

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

		$sql = "
            SELECT
                usuario.id as id,
                email_verificado_em,
                usuario_perfil.id_perfil,
                perfil.descricao,
				assistente.documento
            FROM usuario, pessoa, profissional, assistente, usuario_perfil, perfil
            WHERE
                usuario.id_pessoa = pessoa.id AND
                usuario_perfil.id_usuario = usuario.id AND
                perfil.id = usuario_perfil.id_perfil AND
                pessoa.id = profissional.id_pessoa AND
                assistente.id_profissional = profissional.id AND
                usuario.email = :email: AND
                usuario.senha = :passwd: AND
        	    usuario.ativo = 1
            LIMIT 1
        ";
		return $this->authenticateUser( $email, $passwd, $sql );

	}

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

		$sql = "
            SELECT
                usuario.id as id,
                email_verificado_em,
                usuario_perfil.id_perfil,
                perfil.descricao,
				administrativo.documento
            FROM usuario, pessoa, profissional, administrativo, usuario_perfil, perfil
            WHERE
                usuario.id_pessoa = pessoa.id AND
                usuario_perfil.id_usuario = usuario.id AND
                perfil.id = usuario_perfil.id_perfil AND
                pessoa.id = profissional.id_pessoa AND
                administrativo.id_profissional = profissional.id AND
                usuario.email = :email: AND
                usuario.senha = :passwd: AND
        	    usuario.ativo = 1
            LIMIT 1
        ";
		return $this->authenticateUser( $email, $passwd, $sql );

	}

	public function authenticateUser(string $email, string $passwd, string $sql): DAOResponse {

		$binds = [ 
			'email' => $email,
			'passwd' => $passwd
		];
		$query = $this->db->query( $sql, $binds );
		$error = $this->db->error();
		$dao_response = new DAOResponse();
		if ($error && $error ['code']) {
			$dao_response->setStatus( $error ['code'] );
			$log_service = new LogService();
			$log_service->log_error( $error ['code'], 'Ocorreu um erro durante a autenticação de um usuário.',
				[ 
					'error' => $error,
					'email' => $email,
					'senha' => $passwd
				] );
		} else {
			$result_array = $query->getResultArray();
			$dao_response->setStatus( count( $result_array ) ? DAOResponseInterface::SUCESS : DAOResponseInterface::RECORD_NOT_FOUND );
			if (count( $result_array )) {
				$user = Usuario::builder()->setId( $result_array [0] ['id'] )
					->setEmailVerificadoEm( $result_array [0] ['id'] )
					->setAlteradoPor( $result_array [0] ['id_perfil'] )
					->setFoto( $result_array [0] ['descricao'] )
					->setDocumento( $result_array [0] ['documento'] ?? '')
					->build();
				$dao_response->setData( $user );
			}
		}
		return $dao_response;

	}

	public function confirmEmailByID(int $id): DAOResponse {

		$sql = '
            UPDATE
                usuario
            INNER JOIN confirmacao_email ON usuario.id = confirmacao_email.id_usuario 
            SET 
                usuario.email_verificado_em = NOW(),
                confirmacao_email.verificado = 1
            WHERE
                confirmacao_email.id = ?
        ';
		$binds = [ 
			$id
		];
		$query = $this->db->query( $sql, $binds );
		$affected_rows = $query->connID->affected_rows;
		$status_response = $affected_rows >= 2 ? DAOResponseInterface::SUCESS : DAOResponseInterface::UNKNOWN_ERROR;
		if ($status_response !== DAOResponseInterface::UNKNOWN_ERROR) {
			$log_service = new LogService();
			$message = 'Ocorreu um erro durante a confirmação do email.';
			$log_data = [ 
				'id' => $id,
				'affected_rows' => $affected_rows
			];
			$log_service->log_error( $status_response, $message, $log_data );
		}
		$dao_response = DAOResponse::builder()->setStatus( $status_response )
			->build();
		return $dao_response;

	}

	public function getConfirmacaoEmailByToken(string $token): DAOResponse {

		$sql = '
            SELECT 
                confirmacao_email.id,
                confirmacao_email.id_usuario,
                confirmacao_email.criado_em,
                confirmacao_email.alterado_em,
                confirmacao_email.tempo_expiracao,
                confirmacao_email.criado_em,
                confirmacao_email.alterado_em,
                confirmacao_email.verificado
            FROM confirmacao_email, usuario
            WHERE
                usuario.id = confirmacao_email.id_usuario AND
                token = ? AND 
                usuario.email_verificado_em IS NULL
            LIMIT 1
        ';
		$binds = [ 
			$token
		];
		$query = $this->db->query( $sql, $binds );
		$array_response = $query->getResultArray();
		$found = count( $array_response ) > 0;
		if ($found) {
			$array_response [0] ['token'] = $token;
		}
		$confirmacao_email_array = $found ? $array_response [0] : null;
		$dao_response = DAOResponse::builder()->setStatus( $found ? DAOResponseInterface::SUCESS : DAOResponseInterface::RECORD_NOT_FOUND )
			->setData( $confirmacao_email_array )
			->build();
		return $dao_response;

	}

	public function getPermissaoListByUsuarioId(int $usuarioId): array {

		$sql = <<<SQL
		    SELECT
		        p.id_endpoint as endpoint_id
		    FROM permissao p
		    INNER JOIN usuario_perfil up ON p.id_perfil = up.id_perfil
		    WHERE
		        up.id_usuario = $usuarioId
		        AND p.ativo
		    GROUP BY endpoint_id
		SQL;
		$result = $this->db->query( $sql )
			->getResultArray();
		$permissoes = [ ];
		foreach ( $result as $row ) :
			$permissoes [] = ( int ) ($row ['endpoint_id'] ?? 0);
		endforeach
		;
		return $permissoes;

	}

	public function getEndpointIdByControllerAndActionCombined(string $controllerAction): int {

		$sql = <<<SQL
		    SELECT
		        e.id AS endpoint_id
		    FROM permissao p
		    INNER JOIN endpoint e ON p.id_endpoint = e.id
		    WHERE
		        concat(e.controller,'::',e.action) = :controllerAction:
		        and p.ativo = 1
		    limit 1
		SQL;
		$binds = [ 
			'controllerAction' => $controllerAction
		];
		$result = $this->db->query( $sql, $binds )
			->getResultArray();
		foreach ( $result as $row ) {
			return ( int ) ($row ['endpoint_id'] ?? 0);
		}
		return 0;

	}

}
