<?php

namespace App\DAO;

use App\ChameFacil\UsuarioServiceCF;
use App\DAO\DAOResponse\DAOResponse;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\DAO\Pagination\Pagination;
use App\Entities\CEP\CEP;
use App\Entities\Cliente\Cliente;
use App\Entities\ConfirmacaoEmail\ConfirmacaoEmail;
use App\Entities\Endereco\Endereco;
use App\Entities\Medico\Medico;
use App\Entities\Pessoa\Pessoa;
use App\Entities\PessoaFisica\PessoaFisica;
use App\Entities\Profissional\Profissional;
use App\Entities\ProfissionalClinica\ProfissionalClinica;
use App\Entities\Usuario\Usuario;
use App\Entities\UsuarioPerfil\UsuarioPerfil;
use App\Mappers\MedicoMapper;
use App\Models\CEPModel;
use App\Models\ClienteModel;
use App\Models\ConfirmacaoEmailModel;
use App\Models\EnderecoModel;
use App\Models\MedicoModel;
use App\Models\PacienteModel;
use App\Models\PessoaFisicaModel;
use App\Models\PessoaModel;
use App\Models\ProfissionalClinicaModel;
use App\Models\ProfissionalModel;
use App\Models\UsuarioModel;
use App\Models\UsuarioPerfilModel;
use App\ChameFacil\AuthBaseServiceCF;
use App\Services\LogService;
use App\Services\ServiceResponse\ServiceResponseInterface;
use App\Utils\Collections\QueryFilterCollection;
use App\Utils\Collections\QueryOrderCollection;
use App\ViewModels\Medico\MedicoRegistrationViewModel\MedicoRegistrationViewModel;
use App\ViewModels\Medico\MedicoUpdateViewModel\MedicoUpdateViewModel;
use Exception;

class MedicoDAO extends DAO {

	public function getMedicoIDFromUsuarioID(int $id_usuario): DAOResponse {

		$sql = '
            SELECT
                medico.id as id_medico
            FROM
                usuario, profissional, medico
            WHERE 
                usuario.id_pessoa = profissional.id_pessoa AND
                medico.id_profissional = profissional.id AND
                usuario.id = :id_usuario:
        ';
		$binds = [ 
			'id_usuario' => $id_usuario
		];
		return $this->getDAOResponseFromUniqueRowSelect( $binds, null, $sql,
			function (array $result_array): int {
				return ( int ) $result_array [0] ['id_medico'];
			} );

	}

	public function persistMedicoRegistrationVM(MedicoRegistrationViewModel $medico_registration_vm, $passwd, callable $send_email): DAOResponse {

		$dao_response = new DAOResponse();
		$auth_chamefacil = new AuthBaseServiceCF();
		$usuario_servce_cf = new UsuarioServiceCF();
		$response_auth = $auth_chamefacil->authBaseService();
		try {
			$this->db->transStart();
			$cep = $this->persistCepFromAssistenteRegistrationVM( $medico_registration_vm );
			$endereco = $this->persistEnderecoFromMedicoRegistrationVM( $medico_registration_vm, $cep );
			$pessoa = $this->persistPessoaFromMedicoRegistrationVM( $medico_registration_vm, $endereco );
			$usuario = $this->persistUsuarioFromMedicoRegistrationVM( $medico_registration_vm, $pessoa );
			# $cliente = $this->persistClienteFromMedicoRegistrationVM( $medico_registration_vm, $pessoa );
			$pessoa_fisica = $this->persistPessoaFisicaFromMedicoRegistrationVM( $medico_registration_vm, $pessoa );
			$usuario_perfil = $this->persistUsuarioPerfilFromMedicoRegistrationVM( $medico_registration_vm, $usuario );
			$profissional = $this->persistProfissionalFromMedicoRegistrationVM( $medico_registration_vm, $pessoa );
			$profissional_clinica = $this->persistProfissionalClinicaFromMedicoRegistrationVM( $medico_registration_vm, $profissional );
			$medico = $this->persistMedicoFromMedicoRegistrationVM( $medico_registration_vm, $profissional );

			if ($medico_registration_vm->getTokenConfirmacaoEmail()) {
				// $confirmacao_email = $this->persistConfirmacaoEmailFromMedicoRegistrationVM( $medico_registration_vm, $usuario );
				$confirmacao_email = true;
			}

			$error = $this->db->error();
			if ($error && $error ['code']) {
				$this->setDatabaseErrorsForMedicoRegistration( $dao_response, $error );
			} else {
				// $status_service_response_send_email = $send_email();
				$status_service_response_send_email = ServiceResponseInterface::SUCESS;
				if ($status_service_response_send_email === ServiceResponseInterface::SUCESS) {
					$usuario_edit_chamefacil = new UsuarioModel();
					$response_usuario = $usuario_servce_cf->createUsuarioCf( $response_auth, $medico_registration_vm,
					$medico_registration_vm->getSenhaChameFacil() );
					$usuario_edit_chamefacil->updateIdChameFacilByUsuarioID( $usuario->getId(), $response_usuario->Codigo ?? 0);
					if ($response_usuario->Codigo > 0) {
						$dao_response->setStatus( DAOResponseInterface::SUCESS );
						$this->db->transComplete();
					} else {
						(new LogService())->log_error( $status_service_response_send_email, 'Falha ao criar usuário do médico no chame fácil.',
							$medico_registration_vm->toArray() );
						$dao_response->setStatus( DAOResponseInterface::INTERNAL_DAO_ERROR );
					}
				} else {
					(new LogService())->log_error( $status_service_response_send_email, 'Falha no envio do email de confirmação de cadastro de um medico.',
						$medico_registration_vm->toArray() );
					$dao_response->setStatus( DAOResponseInterface::INTERNAL_DAO_ERROR );
				}
			}
		} catch ( Exception $exception ) {
			$this->setDatabaseErrorsForMedicoRegistration( $dao_response, $this->db->error() );
		}
		return $dao_response;

	}

	private function setDatabaseErrorsForMedicoRegistration(DAOResponse $dao_response, array $error): void {

		if ($error ['code']) {
			$dao_response->setStatus( $error ['code'] );
			$dao_response->setErrors( $this->getDatabaseResponseErrorsForPersistence( $error ) );
		} else {
			$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
		}
		log_message( 'error', json_encode( $error ) );

	}

	private function persistCepFromAssistenteRegistrationVM(MedicoRegistrationViewModel &$assistente_registration_vm): CEP {

		$cep_model = new CEPModel();
		$cep = MedicoMapper::getCepFromMedicoRegistrationVM( $assistente_registration_vm );
		$cep_model->registerCep( $cep );
		if (!$cep->getId()) {
			throw new Exception( 'O cadastro de cep não foi teve êxito' );
		}
		return $cep;

	}

	private function persistEnderecoFromMedicoRegistrationVM(MedicoRegistrationViewModel &$medico_registration_vm, CEP $cep): Endereco {

		$endereco_model = new EnderecoModel();
		$endereco = MedicoMapper::getEnderecoFromMedicoRegistrationVM( $medico_registration_vm, $cep );
		$endereco_model->registerEndereco( $endereco );
		if (!$endereco->getId()) {
			throw new Exception( 'O cadastro de endereço não foi teve êxito' );
		}
		return $endereco;

	}

	private function persistPessoaFromMedicoRegistrationVM(MedicoRegistrationViewModel &$medico_registration_vm, Endereco &$endereco): Pessoa {

		$pessoa_model = new PessoaModel();
		$pessoa = MedicoMapper::getPessoaFromMedicoRegistrationVM( $medico_registration_vm, $endereco );
		$pessoa_model->registerPessoa( $pessoa );
		if (!$pessoa->getId()) {
			throw new Exception( 'O cadastro de pessoa não foi teve êxito' );
		}
		return $pessoa;

	}

	private function persistPessoaFisicaFromMedicoRegistrationVM(MedicoRegistrationViewModel &$medico_registration_vm, Pessoa &$pessoa): PessoaFisica {

		$pessoa_fisica_model = new PessoaFisicaModel();
		$pessoa_fisica = MedicoMapper::getPessoaFisicaFromMedicoRegistrationVM( $medico_registration_vm, $pessoa );
		$pessoa_fisica_model->registerPessoaFisica( $pessoa_fisica );
		if (!$pessoa_fisica->getId()) {
			throw new Exception( 'O cadastro de pessoa_fisica não foi teve êxito' );
		}
		return $pessoa_fisica;

	}

	private function persistUsuarioFromMedicoRegistrationVM(MedicoRegistrationViewModel &$medico_registration_vm, Pessoa &$pessoa): Usuario {

		$usuario_model = new UsuarioModel();
		$usuario = MedicoMapper::getUsuarioFromMedicoRegistrationVM( $medico_registration_vm, $pessoa );
		$usuario_model->registerUsuario( $usuario );
		if (!$usuario->getId()) {
			throw new Exception( 'O cadastro de usuario não foi teve êxito' );
		}
		return $usuario;

	}

	private function persistClienteFromMedicoRegistrationVM(MedicoRegistrationViewModel &$medico_registration_vm, Pessoa &$pessoa): Cliente {

		$cliente_model = new CLienteModel();
		$cliente = MedicoMapper::getClienteFromMedicoRegistrationVM( $medico_registration_vm, $pessoa );
		$cliente_model->registerCliente( $cliente );
		if (!$cliente->getId()) {
			throw new Exception( 'O cadastro de cliente não foi teve êxito' );
		}
		return $cliente;

	}

	private function persistUsuarioPerfilFromMedicoRegistrationVM(MedicoRegistrationViewModel &$medico_registration_vm, Usuario &$usuario): UsuarioPerfil {

		$usuario_perfil_model = new UsuarioPerfilModel();
		$usuario_perfil = MedicoMapper::getUsuarioPerfilFromMedicoRegistrationVM( $medico_registration_vm, $usuario );
		$usuario_perfil_model->registerUsuarioPerfil( $usuario_perfil );
		if (!$usuario_perfil->getId()) {
			throw new Exception( 'O cadastro de usuario_perfil não foi teve êxito' );
		}
		return $usuario_perfil;

	}

	private function persistConfirmacaoEmailFromMedicoRegistrationVM(MedicoRegistrationViewModel &$medico_registration_vm, Usuario &$usuario): ConfirmacaoEmail {

		$confirmacao_email_model = new ConfirmacaoEmailModel();
		$confirmacao_email = MedicoMapper::getConfirmacaoEmailFromMedicoRegistrationVM( $medico_registration_vm, $usuario );
		$confirmacao_email_model->registerConfirmacaoEmail( $confirmacao_email );
		if (!$confirmacao_email->getId()) {
			throw new Exception( 'O cadastro de confirmação_email não foi teve êxito' );
		}
		return $confirmacao_email;

	}

	private function persistProfissionalFromMedicoRegistrationVM(MedicoRegistrationViewModel &$medico_registration_vm, Pessoa &$pessoa): Profissional {

		$profissional_model = new ProfissionalModel();
		$profissional = MedicoMapper::getProfissionalFromMedicoRegistrationVM( $medico_registration_vm, $pessoa );
		$profissional_model->registerProfissional( $profissional );
		if (!$profissional->getId()) {
			throw new Exception( 'O cadastro de profissional não foi teve êxito' );
		}
		return $profissional;

	}

	private function persistProfissionalClinicaFromMedicoRegistrationVM(MedicoRegistrationViewModel &$medico_registration_vm, Profissional &$pessoa): ProfissionalClinica {

		$profissional_clinica_model = new ProfissionalClinicaModel();
		$array = explode( ",", $medico_registration_vm->getUnidade() );
		foreach ( $array as $unidade ) :
			$profissional_clinica = MedicoMapper::getProfissionalClinicaFromProfissionalClinicaRegistrationVM( $medico_registration_vm, $pessoa, $unidade );
			$profissional_clinica_model->registerProfissionalClinica( $profissional_clinica );
			if (!$profissional_clinica->getId()) {
				throw new Exception( 'O cadastro de medico_clinica não foi teve êxito' );
			}
		endforeach
		;
		return $profissional_clinica;

	}

	private function persistMedicoFromMedicoRegistrationVM(MedicoRegistrationViewModel &$medico_registration_vm, Profissional &$pessoa): Medico {

		$medico_model = new MedicoModel();
		$medico = MedicoMapper::getMedicoFromMedicoRegistrationVM( $medico_registration_vm, $pessoa );
		$medico_model->registerMedico( $medico );
		if (!$medico->getId()) {
			throw new Exception( 'O cadastro de medico não teve êxito' );
		}
		return $medico;

	}

	public function getMedicoList(int $id_status, ?Pagination $pagination, ?QueryFilterCollection $query_filter_collection,
			?QueryOrderCollection $query_order_collection = null): DAOResponse {

		if ($query_filter_collection->length == 0) {
			$sql = $this->getSqlMedicoPorStatus( $id_status );
			// $sql = <<<SQL
			// SELECT
			// medico.id as id,
			// medico.documento as documento,
			// pessoa_fisica.cpf as cpf,
			// pessoa_fisica.rg as rg,
			// pessoa_fisica.nome as nome,
			// pessoa_fisica.genero as genero,
			// pessoa_fisica.profissao as profissao,
			// pessoa_fisica.estado_civil as estado_civil,
			// SUBSTRING(pessoa_fisica.data_nascimento, 1, 10) AS data_nascimento,
			// pessoa.telefone_1 as telefone_1,
			// pessoa.telefone_2 as telefone_2,
			// cep.cep as cep,
			// endereco.numero as numero,
			// endereco.complemento as complemento,
			// endereco.referencias as referencias,
			// cep.estado as estado,
			// cep.cidade as cidade,
			// cep.bairro as bairro,
			// cep.logradouro as logradouro,
			// usuario.ativo as ativo,
			// usuario_status.descricao as status_desc,
			// usuario.email as email,
			// usuario.foto as foto
			// FROM
			// medico, usuario, usuario_status, usuario_perfil , perfil, pessoa,
			// pessoa_fisica, profissional,endereco , cep
			// WHERE
			// usuario.id = usuario_perfil.id_usuario
			// and usuario.ativo = usuario_status.id
			// and usuario_perfil.id_perfil = perfil.id
			// and perfil.id = 2
			// and usuario.id_pessoa = pessoa.id
			// and pessoa_fisica.id_pessoa = pessoa.id
			// and profissional.id_pessoa = pessoa.id
			// and medico.id_profissional = profissional.id
			// and pessoa.id_endereco = endereco.id
			// and cep.id = endereco.cep
			// SQL;
		} else {
			$sql = $this->getSqlMedicoPorStatusComFiltro( $id_status );
			// $sql = <<<SQL
			// SELECT distinct
			// medico.id as id,
			// medico.documento as documento,
			// pessoa_fisica.cpf as cpf,
			// pessoa_fisica.rg as rg,
			// pessoa_fisica.nome as nome,
			// pessoa_fisica.genero as genero,
			// pessoa_fisica.profissao as profissao,
			// pessoa_fisica.estado_civil as estado_civil,
			// SUBSTRING(pessoa_fisica.data_nascimento, 1, 10) AS data_nascimento,
			// pessoa.telefone_1 as telefone_1,
			// pessoa.telefone_2 as telefone_2,
			// cep.cep as cep,
			// endereco.numero as numero,
			// endereco.complemento as complemento,
			// endereco.referencias as referencias,
			// cep.estado as estado,
			// cep.cidade as cidade,
			// cep.bairro as bairro,
			// cep.logradouro as logradouro,
			// usuario.ativo as ativo,
			// usuario_status.descricao as ativo_desc,
			// usuario.email as email,
			// usuario.foto as foto
			// FROM medico , profissional, pessoa, pessoa_fisica,
			// endereco, cep, usuario, usuario_status, profissional_clinica, unidade
			// WHERE
			// medico.id_profissional = profissional.id
			// and profissional.id_pessoa = pessoa.id
			// and pessoa_fisica.id_pessoa = pessoa.id
			// and pessoa.id_endereco = endereco.id
			// and cep.id = endereco.cep
			// and usuario.id_pessoa = pessoa.id
			// and usuario.ativo = usuario_status.id
			// and profissional_clinica.id_profissional = profissional.id
			// and unidade.id_pessoa_juridica = profissional_clinica.id_pessoa_juridica
			// SQL;
		}
		$binds = [ ];
		return $this->getDAOResponseFromPaginatedSelect( $binds, $pagination, $query_filter_collection, $query_order_collection, $sql,
			function (array $result_array) {
				return MedicoMapper::getMedicoVMListFromArray( $result_array );
			} );

	}

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

		$sql = <<<SQL
			select distinct
				m.id, m.documento, ps.telefone_1, pf.cpf , pf.nome ,u.email , u.id as usuario_id
			from 
				medico m , profissional p, pessoa ps, pessoa_fisica pf, usuario u,usuario_perfil up
			where
				m.id_profissional  = p.id
				and p.id_pessoa = ps.id
				and p.id_pessoa = pf.id_pessoa
				and p.id_pessoa = u.id_pessoa
				and u.id = up.id_usuario
				and up.id_perfil = 2
		SQL;

		$binds = [ ];
		return $this->getDAOResponseFromPaginatedSelect( $binds, $pagination, $query_filter_collection, $query_order_collection, $sql,
			function (array $result_array) {
				return MedicoMapper::getMedicoVMListFromArray( $result_array );
			} );

	}

	public function getMedico(QueryFilterCollection $query_filter_collection): DAOResponse {

		// $sql = '
		// SELECT
		// medico.id as id,
		// medico.documento as documento,
		// pessoa_fisica.cpf as cpf,
		// pessoa_fisica.rg as rg,
		// pessoa_fisica.nome as nome,
		// pessoa_fisica.genero as genero,
		// pessoa_fisica.profissao as profissao,
		// pessoa_fisica.estado_civil as estado_civil,
		// SUBSTRING(pessoa_fisica.data_nascimento, 1, 10) AS data_nascimento,
		// pessoa.telefone_1 as telefone_1,
		// pessoa.telefone_2 as telefone_2,
		// cep.cep as cep,
		// endereco.numero as numero,
		// endereco.complemento as complemento,
		// endereco.referencias as referencias,
		// cep.estado as estado,
		// cep.cidade as cidade,
		// cep.bairro as bairro,
		// cep.logradouro as logradouro,
		// usuario.email as email,
		// usuario.foto as foto
		// FROM medico
		// INNER JOIN profissional ON medico.id_profissional = profissional.id
		// INNER JOIN pessoa ON profissional.id_pessoa = pessoa.id
		// INNER JOIN pessoa_fisica ON pessoa_fisica.id_pessoa = pessoa.id
		// INNER JOIN endereco ON pessoa.id_endereco = endereco.id
		// INNER JOIN cep ON cep.id = endereco.cep
		// INNER JOIN usuario ON usuario.id_pessoa = pessoa.id
		// WHERE
		// usuario.ativo = 1
		// ';
		$sql = <<<SQL
			SELECT distinct
				medico.id as id,
				medico.documento as documento,
				pessoa_fisica.cpf as cpf,
				pessoa_fisica.rg as rg,
				pessoa_fisica.nome as nome,
				pessoa_fisica.genero as genero,
				pessoa_fisica.profissao as profissao,
				pessoa_fisica.estado_civil as estado_civil,
				SUBSTRING(pessoa_fisica.data_nascimento, 1, 10) AS data_nascimento,
				pessoa.telefone_1 as telefone_1,
				pessoa.telefone_2 as telefone_2,
				cep.cep as cep,
				endereco.numero as numero,
				endereco.complemento as complemento,
				endereco.referencias as referencias,
				cep.estado as estado,
				cep.cidade as cidade,
				cep.bairro as bairro,
				cep.logradouro as logradouro,
				usuario.ativo as ativo,
				usuario_status.descricao as ativo_desc,
				usuario.email as email,
				usuario.foto as foto
			FROM medico , profissional, pessoa, pessoa_fisica,
				endereco, cep, usuario, usuario_status, profissional_clinica, unidade
			WHERE
				medico.id_profissional = profissional.id
				and profissional.id_pessoa = pessoa.id
				and pessoa_fisica.id_pessoa = pessoa.id
				and pessoa.id_endereco = endereco.id
				and cep.id = endereco.cep
				and usuario.id_pessoa = pessoa.id
				and usuario.ativo = usuario_status.id
				and profissional_clinica.id_profissional = profissional.id
				and unidade.id_pessoa_juridica = profissional_clinica.id_pessoa_juridica
		SQL;
		$binds = [ ];
		return $this->getDAOResponseFromUniqueRowSelect( $binds, $query_filter_collection, $sql,
			function (array $result_array) {
				return MedicoMapper::getMedicoDetailsVMFromArray( $result_array [0] );
			} );

	}

	private function getDatabaseResponseErrorsForPersistence(array $error): array {

		$dao_response_errors = [ ];
		if ($error && $error ['code']) {
			if ($error ['code'] === DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS) {
				if (strpos( $error ['message'], 'cep' ) !== false) {
					$dao_response_errors ['cep'] = 'Esse cep não existe.';
				}
			} else if ($error ['code'] === DAOResponseInterface::DUPLICATED_UNIQUE_KEY) {
				if (strpos( $error ['message'], '\'pessoa_fisica.cpf\'' ) !== false) {
					$dao_response_errors ['cpf'] = 'Uma pessoa com esse CPF já está cadastrada no sistema.';
				}
				if (strpos( $error ['message'], '\'pessoa_fisica.rg\'' ) !== false) {
					$dao_response_errors ['rg'] = 'Uma pessoa com esse RG já está cadastrada no sistema.';
				}
				if (strpos( $error ['message'], '\'usuario.email\'' ) !== false) {
					$dao_response_errors ['email'] = 'Uma pessoa com esse email já está cadastrada no sistema.';
				}
			}
		}
		return $dao_response_errors;

	}

	public function verifyMedicoAndMedicoAreLinked(int $id_medico, int $medico_uid): DAOResponse {

		$sql = '
            SELECT
                1
            FROM assistente_medico, assistente, profissional, usuario
            WHERE 
                assistente_medico.id_assistente = assistente.id AND
                profissional.id = assistente.id_profissional AND
                usuario.id_pessoa = profissional.id_pessoa AND
                usuario.id = :assistente_uid: AND
                id_medico = :id_medico:
            LIMIT 1
        ';
		$binds = [ 
			'id_medico' => $id_medico,
			'assistente_uid' => $medico_uid
		];
		return $this->getDAOResponseFromUniqueRowSelect( $binds, null, $sql, function (array $result_array): bool {
			return true;
		} );

	}

	public function persistMedicoUpdateVM(int $id_paciente, MedicoUpdateViewModel $medico_update_vm): DAOResponse {

		$dao_response = new DAOResponse();
		$this->db->transStart();
		$status_persistence = $this->persistCepFromMedicoUpdateVM( $id_paciente, $medico_update_vm );
		$status_persistence = $status_persistence && $this->persistEnderecoFromMedicoUpdateVM( $id_paciente, $medico_update_vm );
		$status_persistence = $status_persistence && $this->persistPessoaFromMedicoUpdateVM( $id_paciente, $medico_update_vm );
		$status_persistence = $status_persistence && $this->persistUsuarioFromMedicoUpdateVM( $id_paciente, $medico_update_vm );
		$status_persistence = $status_persistence && $this->persistPessoaFisicaFromMedicoUpdateVM( $id_paciente, $medico_update_vm );
		$status_persistence = $status_persistence && $this->persistMedicoFromMedicoUpdateVM( $id_paciente, $medico_update_vm );
		$error = $this->db->error();
		if ($error && $error ['code']) {
			$this->setDatabaseErrorsForMedicoUpdate( $dao_response, $error );
			return $dao_response;
		} else if ($status_persistence) {
			$this->db->transComplete();
			$dao_response->setStatus( DAOResponseInterface::SUCESS );
		}
		$this->db->close();
		return $dao_response;

	}

	private function setDatabaseErrorsForMedicoUpdate(DAOResponse $dao_response, array $error): void {

		$dao_response->setStatus( $error ['code'] );
		$dao_response->setErrors( $this->getDatabaseResponseErrorsForPersistence( $error ) );

	}

	private function persistCepFromMedicoUpdateVM(int $id_paciente, MedicoUpdateViewModel &$paciente_update_vm): bool {

		$cep_model = new CEPModel();
		$cep = MedicoMapper::getCepFromMedicoUpdateVM( $paciente_update_vm );
		$sucess_update = $cep_model->updateCepByMedicoID( $id_paciente, $cep );
		return $sucess_update;

	}

	private function persistEnderecoFromMedicoUpdateVM(int $id_paciente, MedicoUpdateViewModel &$medico_update_vm): bool {

		$endereco_model = new EnderecoModel();
		$endereco = MedicoMapper::getEnderecoFromMedicoUpdateVM( $medico_update_vm );
		$sucess_update = $endereco_model->updateEnderecoByMedicoID( $id_paciente, $endereco );
		return $sucess_update;

	}

	private function persistPessoaFromMedicoUpdateVM(int $id_assistente, MedicoUpdateViewModel &$medico_update_vm): bool {

		$pessoa_model = new PessoaModel();
		$pessoa = MedicoMapper::getPessoaFromMedicoUpdateVM( $medico_update_vm );
		$sucess_update = $pessoa_model->updatePessoaByMedicoID( $id_assistente, $pessoa );
		return $sucess_update;

	}

	private function persistPessoaFisicaFromMedicoUpdateVM(int $id_assistente, MedicoUpdateViewModel &$medico_update_vm): bool {

		$pessoa_fisica_model = new PessoaFisicaModel();
		$pessoa_fisica = MedicoMapper::getPessoaFisicaFromMedicoUpdateVM( $medico_update_vm );
		$sucess_update = $pessoa_fisica_model->updatePessoaFisicaByMedicoID( $id_assistente, $pessoa_fisica );
		return $sucess_update;

	}

	private function persistMedicoFromMedicoUpdateVM(int $id_medico, MedicoUpdateViewModel &$medico_update_vm): bool {

		$pessoa_fisica_model = new MedicoModel();
		$pessoa_fisica = MedicoMapper::getMedicoFromMedicoUpdateVM( $medico_update_vm );
		$sucess_update = $pessoa_fisica_model->updateMedicoByMedicoID( $id_medico, $pessoa_fisica );
		return $sucess_update;

	}

	private function persistUsuarioFromMedicoUpdateVM(int $id_assistente, MedicoUpdateViewModel &$medico_update_vm): bool {

		$usuario_model = new UsuarioModel();
		$usuario = MedicoMapper::getUsuarioFromMedicoUpdateVM( $medico_update_vm );
		$sucess_update = $usuario_model->updateUsuarioByMedicoID( $id_assistente, $usuario );
		return $sucess_update;

	}

	public function getImageMedico(int $id_medico) {

		$sql = '
            SELECT
                usuario.foto as foto
            FROM medico
                INNER JOIN profissional ON medico.id_profissional = profissional.id 
                INNER JOIN pessoa ON profissional.id_pessoa = pessoa.id
                INNER JOIN pessoa_fisica ON pessoa_fisica.id_pessoa = pessoa.id
                INNER JOIN endereco ON pessoa.id_endereco = endereco.id
                INNER JOIN cep ON cep.id = endereco.cep 
                INNER JOIN usuario ON usuario.id_pessoa = pessoa.id
            WHERE
            	usuario.ativo = 1 AND medico.id = :id_medico:
        ';
		$binds = [ 
			'id_medico' => $id_medico
		];
		$query = $this->db->query( $sql, $binds );
		$result_array = $query->getResultArray();
		return (($result_array [0] ['foto']));

	}

	public function getMedicoFromId(int $id_medico) {

		$sql = '
            SELECT 1
            FROM medico
            WHERE medico.id = :id_medico:
        ';
		$binds = [ 
			'id_medico' => $id_medico
		];
		$query = $this->db->query( $sql, $binds );
		$result_array = $query->getResultArray();
		return ($result_array);

	}

	public function getUnidadesMedico(int $id_medico) {

		$sql = '
            SELECT 
            u.id as id_unidade,
            u.descricao as descricao_unidade,
            u.id_pessoa_juridica as id_pessoa_juridica
            FROM medico m
            INNER JOIN profissional_clinica pc on pc.id_profissional = m.id_profissional 
            INNER JOIN unidade u on u.id_pessoa_juridica = pc.id_pessoa_juridica 
            WHERE m.id = :id_medico:
        ';
		$binds = [ 
			'id_medico' => $id_medico
		];
		$query = $this->db->query( $sql, $binds );
		$result_array = $query->getResultArray();
		return ($result_array);

	}

	private function getSqlMedicoPorStatus(int $id_status) {

		$sql = '';
		switch ($id_status) {
			case 1 :
				$sql = <<<SQL
					SELECT
						medico.id as id,
						medico.documento as documento,
						pessoa_fisica.cpf as cpf,
						pessoa_fisica.rg as rg,
						pessoa_fisica.nome as nome,
						pessoa_fisica.genero as genero,
						pessoa_fisica.profissao as profissao,
						pessoa_fisica.estado_civil as estado_civil,
						SUBSTRING(pessoa_fisica.data_nascimento, 1, 10) AS data_nascimento,
						pessoa.telefone_1 as telefone_1,
						pessoa.telefone_2 as telefone_2,
						cep.cep as cep,
						endereco.numero as numero,
						endereco.complemento as complemento,
						endereco.referencias as referencias,
						cep.estado as estado,
						cep.cidade as cidade,
						cep.bairro as bairro,
						cep.logradouro as logradouro,
						usuario.ativo as ativo,
						usuario_status.descricao as status_desc,
						usuario.email as email,
						usuario.foto as foto
					FROM
						medico, usuario, usuario_status, usuario_perfil , perfil, pessoa,
						pessoa_fisica, profissional,endereco , cep
					WHERE
						usuario.id = usuario_perfil.id_usuario
						and usuario.ativo = 1
						and usuario.ativo = usuario_status.id
						and usuario_perfil.id_perfil = perfil.id
						and perfil.id = 2
						and usuario.id_pessoa = pessoa.id
						and pessoa_fisica.id_pessoa = pessoa.id
						and profissional.id_pessoa = pessoa.id
						and medico.id_profissional = profissional.id
						and pessoa.id_endereco = endereco.id
						and cep.id = endereco.cep
				SQL;

				break;
			case 2 :
				$sql = <<<SQL
					SELECT
						medico.id as id,
						medico.documento as documento,
						pessoa_fisica.cpf as cpf,
						pessoa_fisica.rg as rg,
						pessoa_fisica.nome as nome,
						pessoa_fisica.genero as genero,
						pessoa_fisica.profissao as profissao,
						pessoa_fisica.estado_civil as estado_civil,
						SUBSTRING(pessoa_fisica.data_nascimento, 1, 10) AS data_nascimento,
						pessoa.telefone_1 as telefone_1,
						pessoa.telefone_2 as telefone_2,
						cep.cep as cep,
						endereco.numero as numero,
						endereco.complemento as complemento,
						endereco.referencias as referencias,
						cep.estado as estado,
						cep.cidade as cidade,
						cep.bairro as bairro,
						cep.logradouro as logradouro,
						usuario.ativo as ativo,
						usuario_status.descricao as status_desc,
						usuario.email as email,
						usuario.foto as foto
					FROM
						medico, usuario, usuario_status, usuario_perfil , perfil, pessoa,
						pessoa_fisica, profissional,endereco , cep
					WHERE
						usuario.id = usuario_perfil.id_usuario
						and usuario.ativo = 2
						and usuario.ativo = usuario_status.id
						and usuario_perfil.id_perfil = perfil.id
						and perfil.id = 2
						and usuario.id_pessoa = pessoa.id
						and pessoa_fisica.id_pessoa = pessoa.id
						and profissional.id_pessoa = pessoa.id
						and medico.id_profissional = profissional.id
						and pessoa.id_endereco = endereco.id
						and cep.id = endereco.cep
				SQL;
				break;

			default :
				$sql = <<<SQL
					SELECT
						medico.id as id,
						medico.documento as documento,
						pessoa_fisica.cpf as cpf,
						pessoa_fisica.rg as rg,
						pessoa_fisica.nome as nome,
						pessoa_fisica.genero as genero,
						pessoa_fisica.profissao as profissao,
						pessoa_fisica.estado_civil as estado_civil,
						SUBSTRING(pessoa_fisica.data_nascimento, 1, 10) AS data_nascimento,
						pessoa.telefone_1 as telefone_1,
						pessoa.telefone_2 as telefone_2,
						cep.cep as cep,
						endereco.numero as numero,
						endereco.complemento as complemento,
						endereco.referencias as referencias,
						cep.estado as estado,
						cep.cidade as cidade,
						cep.bairro as bairro,
						cep.logradouro as logradouro,
						usuario.ativo as ativo,
						usuario_status.descricao as status_desc,
						usuario.email as email,
						usuario.foto as foto
					FROM
						medico, usuario, usuario_status, usuario_perfil , perfil, pessoa,
						pessoa_fisica, profissional,endereco , cep
					WHERE
						usuario.id = usuario_perfil.id_usuario					
						and usuario.ativo = usuario_status.id
						and usuario_perfil.id_perfil = perfil.id
						and perfil.id = 2
						and usuario.id_pessoa = pessoa.id
						and pessoa_fisica.id_pessoa = pessoa.id
						and profissional.id_pessoa = pessoa.id
						and medico.id_profissional = profissional.id
						and pessoa.id_endereco = endereco.id
						and cep.id = endereco.cep
				SQL;
				break;
		}

		return $sql;

	}

	private function getSqlMedicoPorStatusComFiltro(int $id_status) {

		$sql = '';
		switch ($id_status) {
			case 1 :
				$sql = <<<SQL
						SELECT distinct
						medico.id as id,
						medico.documento as documento,
						pessoa_fisica.cpf as cpf,
						pessoa_fisica.rg as rg,
						pessoa_fisica.nome as nome,
						pessoa_fisica.genero as genero,
						pessoa_fisica.profissao as profissao,
						pessoa_fisica.estado_civil as estado_civil,
						SUBSTRING(pessoa_fisica.data_nascimento, 1, 10) AS data_nascimento,
						pessoa.telefone_1 as telefone_1,
						pessoa.telefone_2 as telefone_2,
						cep.cep as cep,
						endereco.numero as numero,
						endereco.complemento as complemento,
						endereco.referencias as referencias,
						cep.estado as estado,
						cep.cidade as cidade,
						cep.bairro as bairro,
						cep.logradouro as logradouro,
						usuario.ativo as ativo,
						usuario_status.descricao as ativo_desc,
						usuario.email as email,
						usuario.foto as foto
					FROM medico , profissional, pessoa, pessoa_fisica,
						endereco, cep, usuario, usuario_status, profissional_clinica, unidade
					WHERE
						medico.id_profissional = profissional.id
						and profissional.id_pessoa = pessoa.id
						and pessoa_fisica.id_pessoa = pessoa.id
						and pessoa.id_endereco = endereco.id
						and cep.id = endereco.cep
						and usuario.id_pessoa = pessoa.id
						and usuario.ativo = usuario_status.id
						and usuario.ativo = 1
						and profissional_clinica.id_profissional = profissional.id
						and unidade.id_pessoa_juridica = profissional_clinica.id_pessoa_juridica
				SQL;
				break;
			case 2 :
				$sql = <<<SQL
						SELECT distinct
						medico.id as id,
						medico.documento as documento,
						pessoa_fisica.cpf as cpf,
						pessoa_fisica.rg as rg,
						pessoa_fisica.nome as nome,
						pessoa_fisica.genero as genero,
						pessoa_fisica.profissao as profissao,
						pessoa_fisica.estado_civil as estado_civil,
						SUBSTRING(pessoa_fisica.data_nascimento, 1, 10) AS data_nascimento,
						pessoa.telefone_1 as telefone_1,
						pessoa.telefone_2 as telefone_2,
						cep.cep as cep,
						endereco.numero as numero,
						endereco.complemento as complemento,
						endereco.referencias as referencias,
						cep.estado as estado,
						cep.cidade as cidade,
						cep.bairro as bairro,
						cep.logradouro as logradouro,
						usuario.ativo as ativo,
						usuario_status.descricao as ativo_desc,
						usuario.email as email,
						usuario.foto as foto
					FROM medico , profissional, pessoa, pessoa_fisica,
						endereco, cep, usuario, usuario_status, profissional_clinica, unidade
					WHERE
						medico.id_profissional = profissional.id
						and profissional.id_pessoa = pessoa.id
						and pessoa_fisica.id_pessoa = pessoa.id
						and pessoa.id_endereco = endereco.id
						and cep.id = endereco.cep
						and usuario.id_pessoa = pessoa.id
						and usuario.ativo = usuario_status.id
						and usuario.ativo = 2
						and profissional_clinica.id_profissional = profissional.id
						and unidade.id_pessoa_juridica = profissional_clinica.id_pessoa_juridica
				SQL;
				break;

			default :
				$sql = <<<SQL
						SELECT distinct
						medico.id as id,
						medico.documento as documento,
						pessoa_fisica.cpf as cpf,
						pessoa_fisica.rg as rg,
						pessoa_fisica.nome as nome,
						pessoa_fisica.genero as genero,
						pessoa_fisica.profissao as profissao,
						pessoa_fisica.estado_civil as estado_civil,
						SUBSTRING(pessoa_fisica.data_nascimento, 1, 10) AS data_nascimento,
						pessoa.telefone_1 as telefone_1,
						pessoa.telefone_2 as telefone_2,
						cep.cep as cep,
						endereco.numero as numero,
						endereco.complemento as complemento,
						endereco.referencias as referencias,
						cep.estado as estado,
						cep.cidade as cidade,
						cep.bairro as bairro,
						cep.logradouro as logradouro,
						usuario.ativo as ativo,
						usuario_status.descricao as ativo_desc,
						usuario.email as email,
						usuario.foto as foto
					FROM medico , profissional, pessoa, pessoa_fisica,
						endereco, cep, usuario, usuario_status, profissional_clinica, unidade
					WHERE
						medico.id_profissional = profissional.id
						and profissional.id_pessoa = pessoa.id
						and pessoa_fisica.id_pessoa = pessoa.id
						and pessoa.id_endereco = endereco.id
						and cep.id = endereco.cep
						and usuario.id_pessoa = pessoa.id
						and usuario.ativo = usuario_status.id					
						and profissional_clinica.id_profissional = profissional.id
						and unidade.id_pessoa_juridica = profissional_clinica.id_pessoa_juridica
				SQL;
				break;
		}

		return $sql;

	}

}