<?php

namespace App\DAO;

use App\DAO\DAOResponse\DAOResponse;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\DAO\Pagination\Pagination;
use App\Entities\Consulta\Consulta;
// use App\Entities\Prontuario\Prontuario;
use App\Entities\RespostaEscolhaOpcao\RespostaEscolhaOpcao;
use App\Entities\RespostaFormulario\RespostaFormulario;
use App\Entities\RespostaNumericaDecimal\RespostaNumericaDecimal;
use App\Entities\RespostaNumericaInteira\RespostaNumericaInteira;
use App\Entities\RespostaTextual\RespostaTextual;
use App\Infra\K2web\K2web;
use App\Mappers\ConsultaMapper;
use App\Models\ConsultaModel;
use App\Models\ModelEntity;
use App\Models\ProntuarioModel;
use App\Models\RespostaEscolhaOpcaoModel;
use App\Models\RespostaFormularioModel;
use App\Models\RespostaNumericaDecimalModel;
use App\Models\RespostaNumericaInteiraModel;
use App\Models\RespostaTextualModel;
use App\Services\JWT\UsuarioLogado;
use App\Services\LogService;
use App\Utils\Collections\GeneralCollection;
use App\Utils\Collections\QueryFilterCollection;
use App\Utils\Collections\QueryOrderCollection;
use App\Utils\DateUtils;
use App\ViewModels\Consulta\ConsultaRegistrationViewModel\ConsultaRegistrationViewModel;
use App\ViewModels\Consulta\ConsultaRegistrationViewModel\RespostaFormularioCollection;
use App\ViewModels\Consulta\ConsultaUpdateViewModel\ConsultaUpdateViewModel;
use CodeIgniter\Model;
use DateInterval;
use DateTime;
use Exception;
use App\Services\AssistenteService;

class ConsultaDAO extends DAO {

	public function registerConsulta(ConsultaRegistrationViewModel $consulta_registration_vm, array $data_post): DAOResponse {

		$dao_response = new DAOResponse();
		$log_service = new LogService();
		$resposta_formulario_model = new RespostaFormularioModel();
		try {
			$this->db->transStart();
			$consulta = $this->persistConsultaByConsultaRegistrationVM( $consulta_registration_vm );
			$prontuario = $this->persistProntuarioByConsultaRegistrationVM( $consulta_registration_vm );
			$insert_decimal = $this->persistRespostaNumericaDecimal( $consulta_registration_vm, $consulta, $resposta_formulario_model );
			$insert_inteira = $insert_decimal && $this->persistRespostaNumericaInteira( $consulta_registration_vm, $consulta, $resposta_formulario_model );
			$insert_texto = $insert_inteira && $this->persistRespostaTextual( $consulta_registration_vm, $consulta, $resposta_formulario_model );
			$insert_escolha_opcao = $insert_texto && $this->persistRespostaEscolhaOpcao( $consulta_registration_vm, $consulta, $resposta_formulario_model );

			// ==============================================================================================
			// Validação de voucher
			// ==============================================================================================

			$sqlIdVoucher = <<<SQL
			    select id_voucher from agendamento_voucher av where id_agendamento = :id_agendamento:
			SQL;

			$binds = [ 
				'id_agendamento' => $consulta_registration_vm->getIdAgendamento()
			];
			$id_voucher = $this->db->query( $sqlIdVoucher, $binds )
				->getResultArray();

			if (count( $id_voucher ) == 1) {
				$sqlAtualizaVoucher = <<<SQL
				    update voucher set id_status = 2 where id = :id_voucher:
				SQL;

				$binds = [ 
					'id_voucher' => $id_voucher [0] ['id_voucher']
				];
				$this->db->query( $sqlAtualizaVoucher, $binds );
			}

			// ==============================================================================================
			// Altera a requisiçao para executado e seta os id do medico de consulta
			// ==============================================================================================

			$id_requisicao_procedimento = $data_post ['id_requisicao_procedimento'];

			$sql_getIdMedico = <<<SQL
			    select
			        agenda.id_medico
			    from agenda, agendamento
			    where
			        agendamento.id_agenda = agenda.id and
			        agendamento.id = :id_agendamento:
			SQL;
			$binds = [ 
				'id_agendamento' => $consulta_registration_vm->getIdAgendamento()
			];
			$id_medico = $this->db->query( $sql_getIdMedico, $binds )
				->getResultArray();

			if ($id_requisicao_procedimento) {

				$sql_requisicao = <<<SQL
				update 
				    requisicao_procedimento 
				set 
				    status_id = 2,
				    id_medico = :id_medico:,
				    id_consulta = :id_consulta:,
				    data_execucao = :data_execucao:,
				    hora_execucao = :hora_execucao:
				    where id = :requisicao_procedimento_id:
				SQL;
				$binds = [ 
					'id_medico' => $id_medico [0] ['id_medico'],
					'id_consulta' => $consulta->getId(),
					'data_execucao' => date( 'Y-m-d' ),
					'hora_execucao' => date( 'H:i:s' ),
					'requisicao_procedimento_id' => $id_requisicao_procedimento
				];
				$conn_req_exec = db_connect();
				$conn_req_exec->query( $sql_requisicao, $binds );
				$req_exec_affectrow = $conn_req_exec->affectedRows();
				$rec_exec_error = $conn_req_exec->error();
				// $conn_req_exec->close();
				// $this->db->query( $sql_requisicao, $binds );

				if ($req_exec_affectrow > 0) {

					$sql_agd_upd = <<<SQL
						update agendamento
						set cancelado_em ='1900-01-01 00:00:00' , 
							alterado_por = :id_usr:, 
							alterado_em = :dt_atz:
						where id = :agendamento_id:
					SQL;

					$bind_agd_upd = [ 
						'agendamento_id' => $consulta_registration_vm->getIdAgendamento(),
						'id_usr' => UsuarioLogado::getUsuarioId(),
						'dt_atz' => DateUtils::now()
					];

					$conn_agd_upd = db_connect();
					$conn_agd_upd->query( $sql_agd_upd, $bind_agd_upd )->numRows;
					$error_agd_upd = $conn_agd_upd->error();
					$agd_upd_affectrow = $conn_agd_upd->affectedRows();
					if ($error_agd_upd ['code'] != 0) {
						$e = $error_agd_upd;
					}

					// ===============================================================================
					// Rotina para atualiza agendamento especialidade quand existe esse agendamento
					// ===============================================================================
					$sql_agd_esp = <<<SQL
						select id from agendamento_especialidade where id_requisicao_procedimento =:requisicao_procedimento_id:
					SQL;
					$bind_agd_esp = [ 
						'requisicao_procedimento_id' => $id_requisicao_procedimento
					];
					$conn_agd_esp = db_connect();
					$result_agd_esp = $conn_agd_esp->query( $sql_agd_esp, $bind_agd_esp )
						->getResultArray();
					$error_agd_esp = $conn_agd_esp->error();

					if ($error_agd_esp ['code'] == 0) {
						if (count( $result_agd_esp ) == 1) {
							$id_agd_esp = $result_agd_esp [0] ['id'];
							$sql_agd_esp_upd = <<<SQL
								update agendamento_especialidade 
								set id_status = 3 , atualizado_por =:id_usr:, data_atualizacao = :dt_atz:, hora_atualizacao =:hr_atz:
								where id = :id_agd:
							SQL;
							$binds_agd_esp_upd = [ 
								'id_usr' => UsuarioLogado::getUsuarioId(),
								'dt_atz' => DateUtils::today(),
								'hr_atz' => DateUtils::now_time(),
								'id_agd' => $id_agd_esp
							];
							$conn_agd_esp_upd = db_connect();
							$conn_agd_esp_upd->query( $sql_agd_esp_upd, $binds_agd_esp_upd )->numRows;
							$agd_esp_affectrow = $conn_agd_esp_upd->affectedRows();
						}
					}

					// ===============================================================================
					// Fim atualização agenda especialidade
					// ===============================================================================

					// =============================================================
					// se procedimento publico marcar como pago na comanda.
					// =============================================================

					$sql_tipo_convenio = <<<SQL
						select 
							rp.id, rp.id_convenio_procedimento , cp.id_convenio  , c.id_tipo_convenio as tipo_convenio_id, 
							tc.descricao as descricao_convenio
						from 
							requisicao_procedimento rp, convenio_procedimento cp  , 
							convenio c , tipo_convenio tc
						where
							rp.id = :requisicaoId:
							and rp.id_convenio_procedimento = cp.id
							and cp.id_convenio  = c.id
							and c.id_tipo_convenio = tc.id 
					SQL;

					$bind_tipo_convenio = [ 
						'requisicaoId' => $id_requisicao_procedimento
					];

					$conn_tipo_convenio = db_connect();
					$resp_tipo_convenio = $conn_tipo_convenio->query( $sql_tipo_convenio, $bind_tipo_convenio )
						->getResultArray();

					$resp_tipo_convenio_error = $conn_tipo_convenio->error();
					// $conn_tipo_convenio->close();

					if (count( $resp_tipo_convenio ) > 0) {
						$tipo_convenio = intval( $resp_tipo_convenio [0] ['tipo_convenio_id'] );
						if ($tipo_convenio == 1) {

							$sql_marca_pago_publico = <<<SQL
								update
									comanda_item
								set
									comanda_item_status_id = 2, -- PAGO:2
									atualizado_por = :usuario:,
									data_atualizacao = :data_atz:,
									hora_atualizacao = :hora_atz:
								where 
									id_requisicao_procedimento = :requisicaoId:
									and comanda_item_status_id = 1 -- NAO PAGO:1
							SQL;

							$usr = UsuarioLogado::getUsuarioId();
							$data_atz = strval( DateUtils::today() );
							$hora_atz = strval( DateUtils::now_time() );

							$bind_marca_pago_publico = [ 
								'usuario' => $usr,
								'data_atz' => $data_atz,
								'hora_atz' => $hora_atz,
								'requisicaoId' => $id_requisicao_procedimento
							];
							$conn_marcar_pago_publico = db_connect();
							$conn_marcar_pago_publico->query( $sql_marca_pago_publico, $bind_marca_pago_publico );
							$affectrow_pago_publico = $conn_marcar_pago_publico->affectedRows();
							$resp_pago_publico_error = $conn_marcar_pago_publico->error();
							// $conn_marcar_pago_publico->close();
						}
					}
				}
			}

			// ==============================================================================================
			// Fim do bloco de marcar como executado
			// ==============================================================================================

			$error = $this->db->error();
			$dao_response->setData( [ 
				"consulta_id" => $consulta->getId()
			] );

			if ($error && $error ['code']) {

				$this->setDatabaseErrorsForConsultaRegistration( $dao_response, $error );
			} else if ($insert_escolha_opcao) {
				$this->db->transComplete();
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
			} else {
				$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			}
		} catch ( Exception $exception ) {
			$log_service->log_error( $exception->getCode(), $exception->getMessage(), [ ] );
			$this->setDatabaseErrorsForConsultaRegistration( $dao_response, $this->db->error() );
		}
		return $dao_response;

	}

	private function setDatabaseErrorsForConsultaRegistration(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 );
		}

	}

	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'], 'fk_escolha_opcao_pergunta_id_opcao_pergunta' ) !== false) {
					$dao_response_errors ['id_opcao'] = 'Essa opção não existe.';
				}
				if (strpos( $error ['message'], 'id_resposta_formulário' ) !== false) {
					$dao_response_errors ['id_resposta_formulario'] = 'Essa resposta de formulário não existe.';
				}
			} else if ($error ['code'] === DAOResponseInterface::DUPLICATED_UNIQUE_KEY) {
				if (strpos( $error ['message'], 'consulta.id_agendamento' ) !== false) {
					$dao_response_errors ['id_agendamento'] = 'Esse agendamento já possui consulta.';
				}
			}
		}
		return $dao_response_errors;

	}

	private function persistConsultaByConsultaRegistrationVM(ConsultaRegistrationViewModel $consulta_registration_vm): Consulta {

		$consulta_model = new ConsultaModel();
		$consulta = ConsultaMapper::getConsultaByConsultaRegistrationVM( $consulta_registration_vm );
		$consulta_model->registerConsulta( $consulta );
		if (!$consulta->getId()) {
			throw new Exception( 'O cadastro de consulta não foi teve êxito' );
		}
		return $consulta;

	}

	private function persistProntuarioByConsultaRegistrationVM(ConsultaRegistrationViewModel $consulta_registration_vm) {

		$agendamento_consulta = $consulta_registration_vm->toArray();
		$id_paciente = $this->getProntuarioIdPaciente( $agendamento_consulta ["id_agendamento"] );

		$id_prontuario = $this->getIssetProntuario( $id_paciente );
		if (($id_prontuario != null) && ($id_prontuario > 0)) {
			return true;
		}

		$prontuario_model = new ProntuarioModel();
		$prontuario = ConsultaMapper::getProntuarioByConsultaRegistrationVM( $consulta_registration_vm, $id_paciente );
		$prontuario_model->registerProntuario( $prontuario );
		if (!$prontuario->getId()) {
			throw new Exception( 'O cadastro de PRONTUARIO não teve êxito' );
		}
		return $prontuario;

	}

	public function getProntuarioIdPaciente(int $id_agendamento) {

		$sql = '
            SELECT agendamento.id_paciente as id_paciente FROM agendamento
            WHERE agendamento.id = :id_agendamento:';
		$binds = [ 
			'id_agendamento' => $id_agendamento
		];
		$query = $this->db->query( $sql, $binds );
		$result_array = $query->getResultArray();
		return (( int ) ($result_array [0] ['id_paciente']));

	}

	public function getIssetProntuario(int $id_paciente) {

		$sql = '
            SELECT prontuario.id_paciente as id_paciente 
            FROM prontuario
            WHERE prontuario.id_paciente = :id_paciente:';
		$binds = [ 
			'id_paciente' => $id_paciente
		];
		$query = $this->db->query( $sql, $binds );
		$result_array = $query->getResultArray();
		return (( int ) ($result_array [0] ['id_paciente']));

	}

	private function persistRespostaNumericaDecimal(ConsultaRegistrationViewModel $consulta_registration_vm, Consulta $consulta,
			RespostaFormularioModel $resposta_formulario_model): bool {

		$respostas_decimal_collection = $this->getRespostasFormulario( $consulta_registration_vm->getRespostaNumericaDecimalCollection(), $consulta,
			$resposta_formulario_model,
			function (int $id_resposta_formulario, float $resposta): RespostaNumericaDecimal {
				return RespostaNumericaDecimal::builder()->setIdRESPOSTAFORMULARIO( $id_resposta_formulario )
					->setResposta( $resposta )
					->build();
			} );
		$resposta_numerica_decimal_model = new RespostaNumericaDecimalModel();
		return $resposta_numerica_decimal_model->registerRespostaNumericaDecimalCollection( $respostas_decimal_collection );

	}

	private function persistRespostaNumericaInteira(ConsultaRegistrationViewModel $consulta_registration_vm, Consulta $consulta,
			RespostaFormularioModel $resposta_formulario_model): bool {

		$respostas_inteira_collection = $this->getRespostasFormulario( $consulta_registration_vm->getRespostaNumericaInteiraCollection(), $consulta,
			$resposta_formulario_model,
			function (int $id_resposta_formulario, int $resposta): RespostaNumericaInteira {
				return RespostaNumericaInteira::builder()->setIdRESPOSTAFORMULARIO( $id_resposta_formulario )
					->setResposta( $resposta )
					->build();
			} );
		$resposta_numerica_inteira_model = new RespostaNumericaInteiraModel();
		return $resposta_numerica_inteira_model->registerRespostaNumericaInteiraCollection( $respostas_inteira_collection );

	}

	private function persistRespostaTextual(ConsultaRegistrationViewModel $consulta_registration_vm, Consulta $consulta,
			RespostaFormularioModel $resposta_formulario_model): bool {

		$respostas_textual_collection = $this->getRespostasFormulario( $consulta_registration_vm->getRespostaTextualCollection(), $consulta,
			$resposta_formulario_model,
			function (int $id_resposta_formulario, string $resposta): RespostaTextual {
				$resposta_txt = RespostaTextual::builder()->setIdRespostaFormulario( $id_resposta_formulario )
					->setResposta( $resposta )
					->build();
				return $resposta_txt;
			} );
		$resposta_numerica_textual_model = new RespostaTextualModel();
		return $resposta_numerica_textual_model->registerRespostaTextualCollection( $respostas_textual_collection );

	}

	private function persistRespostaEscolhaOpcao(ConsultaRegistrationViewModel $consulta_registration_vm, Consulta $consulta,
			RespostaFormularioModel $resposta_formulario_model): bool {

		$respostas_escolha_opcao_collection = $this->getRespostasFormulario( $consulta_registration_vm->getRespostaEscolhaOpcaoCollection(), $consulta,
			$resposta_formulario_model,
			function (int $id_resposta_formulario, GeneralCollection $respostas): GeneralCollection {
				return $respostas->map( 
					function (int $option) use ($id_resposta_formulario): RespostaEscolhaOpcao {
						return RespostaEscolhaOpcao::builder()->setIdRESPOSTAFORMULARIO( $id_resposta_formulario )
							->setIdOPCAOPERGUNTA( $option )
							->build();
					} );
			} );
		$escolha_opcao_collection = new GeneralCollection();
		$respostas_escolha_opcao_collection->forEach( 
			function (GeneralCollection $respostas_escolha_opcao) use ($escolha_opcao_collection) {
				$respostas_escolha_opcao->forEach( 
					function (RespostaEscolhaOpcao $resposta_escolha_opcao) use ($escolha_opcao_collection) {
						$escolha_opcao_collection->push( $resposta_escolha_opcao );
					} );
			} );
		$resposta_numerica_escolha_opcao_model = new RespostaEscolhaOpcaoModel();
		return $resposta_numerica_escolha_opcao_model->registerRespostaEscolhaOpcaoCollection( $escolha_opcao_collection );

	}

	private function getRespostasFormulario(RespostaFormularioCollection $resposta_formulario_vm_collection, Consulta $consulta,
			RespostaFormularioModel $resposta_formulario_model, callable $resposta_formulario_builder): GeneralCollection {

		$resposta_formulario_collection = ConsultaMapper::getRespostaFormularioCollection( $resposta_formulario_vm_collection, $consulta );
		$resposta_formulario_entity_collection = new GeneralCollection();

		$resposta_formulario_collection->forEach( 
			function (RespostaFormulario $resposta_formulario_to_register, int $index) use ($resposta_formulario_vm_collection, $resposta_formulario_model,
			$resposta_formulario_entity_collection, $resposta_formulario_builder): void {
				$resposta_formulario_model->registerRespostaFormulario( $resposta_formulario_to_register );
				if ($resposta_formulario_to_register->getId()) {
					$resposta_formulario_entity_collection->push( 
						$resposta_formulario_builder( $resposta_formulario_to_register->getId(),
							$resposta_formulario_vm_collection->get( $index )
								->getResposta() ) );
				} else {
					throw new Exception( 'Erro no cadastro de resposta_formulario' );
				}
			} );
		return $resposta_formulario_entity_collection;

	}

	# ---------------------------------------------------------------------------------------------------------------#
	public function getConsultaList(int $id_paciente, ?Pagination $pagination, ?QueryFilterCollection $query_filter_collection,
			?QueryOrderCollection $query_order_collection = null): DAOResponse {

		$sql = '
            SELECT
                agendamento.id as id_agendamento,
                consulta.id as id_consulta,
                procedimento.id as id_procedimento,
                procedimento.descricao as procedimento,
                agenda.data as data,
                agenda.hora_inicio as hora_inicio,
                agenda.hora_final as hora_fim,
                consulta.titulo as consulta_titulo,
                consulta.descricao as consulta_descricao
            FROM
                 agendamento
                 INNER JOIN consulta ON agendamento.id = consulta.id_agendamento
                 INNER JOIN procedimento ON agendamento.id_procedimento = procedimento.id
                 INNER JOIN agenda ON agendamento.id_agenda = agenda.id
            WHERE
                  agendamento.id_paciente = :id_paciente:
        ';

		$binds = [ 
			'id_paciente' => $id_paciente
		];
		return $this->getDAOResponseFromPaginatedSelect( $binds, $pagination, $query_filter_collection, $query_order_collection, $sql,
			function (array $result_array): GeneralCollection {
				return ConsultaMapper::getFormularioListingVMCollectionFromArray( $result_array );
			} );

	}

	# ---------------------------------------------------------------------------------------------------------------#
	public function getMinhasConsultasList(int $id_paciente, ?Pagination $pagination, ?QueryFilterCollection $query_filter_collection,
			?QueryOrderCollection $query_order_collection = null): DAOResponse {

		$sql = <<<SQL
		    SELECT
		        agendamento.id as id_agendamento,
		        COALESCE(agendamento.cancelado_em,'0000-00-00 00:00:00') as status,
		        consulta.id as id_consulta,
		        procedimento.id as id_procedimento,
		        procedimento.descricao as procedimento,
		        agenda.data as data,
		        agenda.hora_inicio as hora_inicio,
		        agenda.hora_final as hora_fim,
		        consulta.titulo as consulta_titulo,
		        consulta.descricao as consulta_descricao,
		        pet.id as id_pet,
		        pet.nome as nome_pet,
		        pet.id_raca as id_raca,
		        raca.nome as nome_raca,
		        unidade.descricao as unidade_descricao
		    FROM 
		         agendamento
		         LEFT JOIN consulta ON agendamento.id = consulta.id_agendamento
		         INNER JOIN procedimento ON agendamento.id_procedimento = procedimento.id
		         INNER JOIN agenda ON agendamento.id_agenda = agenda.id
		         INNER JOIN agendamento_pet on agendamento_pet.id_agendamento = agendamento.id
		         INNER JOIN pet on pet.id = agendamento_pet.id_pet
		         INNER JOIN raca on raca.id = pet.id_raca
		         INNER JOIN paciente on paciente.id = agendamento.id_paciente
		         INNER JOIN usuario on usuario.id_pessoa = paciente.id_pessoa
		         INNER JOIN unidade on agenda.id_unidade = unidade.id
		    where usuario.id = :id_usuario: and unidade.id != 24
		    order by agenda.data desc, agenda.hora_inicio desc
		SQL;

		$binds = [ 
			'id_usuario' => $id_paciente
		];
		return $this->getDAOResponseFromPaginatedSelect( $binds, $pagination, $query_filter_collection, $query_order_collection, $sql,
			function (array $result_array): GeneralCollection {
				return ConsultaMapper::getFormularioListingVMCollectionFromArray( $result_array );
			} );

	}

	# ---------------------------------------------------------------------------------------------------------------#
	public function getMinhasConsultasListTelevet(int $id_paciente, ?Pagination $pagination, ?QueryFilterCollection $query_filter_collection,
			?QueryOrderCollection $query_order_collection = null): DAOResponse {

		$sql = <<<SQL
		    SELECT
		        agendamento.id as id_agendamento,
		        COALESCE(agendamento.cancelado_em,'0000-00-00 00:00:00') as status,
		        consulta.id as id_consulta,
		        procedimento.id as id_procedimento,
		        procedimento.descricao as procedimento,
		        agenda.data as data,
		        agenda.hora_inicio as hora_inicio,
		        agenda.hora_final as hora_fim,
		        consulta.titulo as consulta_titulo,
		        consulta.descricao as consulta_descricao,
		        pet.id as id_pet,
		        pet.nome as nome_pet,
		        pet.id_raca as id_raca,
		        raca.nome as nome_raca,
		        unidade.descricao as unidade_descricao,
		        requisicao_sala_video.available as status_sala
		    FROM 
		         agendamento
		         LEFT JOIN consulta ON agendamento.id = consulta.id_agendamento
		         INNER JOIN procedimento ON agendamento.id_procedimento = procedimento.id
		         INNER JOIN agenda ON agendamento.id_agenda = agenda.id
		         INNER JOIN agendamento_pet on agendamento_pet.id_agendamento = agendamento.id
		         INNER JOIN pet on pet.id = agendamento_pet.id_pet
		         INNER JOIN raca on raca.id = pet.id_raca
		         INNER JOIN paciente on paciente.id = agendamento.id_paciente
		         INNER JOIN usuario on usuario.id_pessoa = paciente.id_pessoa
		         INNER JOIN unidade on agenda.id_unidade = unidade.id
		         INNER JOIN requisicao_sala_video on requisicao_sala_video.id_requisicao_procedimento = agendamento.id_requisicao
		         INNER JOIN agendamento_voucher on agendamento_voucher.id_agendamento = agendamento.id
		    where usuario.id = :id_usuario:
		    order by agenda.data desc, agenda.hora_inicio desc
		SQL;

		$binds = [ 
			'id_usuario' => $id_paciente
		];
		return $this->getDAOResponseFromPaginatedSelect( $binds, $pagination, $query_filter_collection, $query_order_collection, $sql,
			function (array $result_array): GeneralCollection {
				return ConsultaMapper::getFormularioListingTelevetVMCollectionFromArray( $result_array );
			} );

	}

	# ---------------------------------------------------------------------------------------------------------------#
	public function getConsultaListByPet(int $id_pet, ?Pagination $pagination, ?QueryFilterCollection $query_filter_collection,
			?QueryOrderCollection $query_order_collection = null): DAOResponse {

		$sql = <<<SQL
			SELECT
				agendamento.id as id_agendamento, agendamento.cancelado_em as status, consulta.id as id_consulta,
				procedimento.id as id_procedimento, procedimento.descricao as procedimento, agenda.data as data,
				agenda.hora_inicio as hora_inicio, agenda.hora_final as hora_fim, consulta.titulo as consulta_titulo,
				consulta.descricao as consulta_descricao, pet.id as id_pet, pet.nome as nome_pet, 
				pet.id_raca as id_raca, raca.nome as nome_raca,
				COALESCE (agenda.id_medico,0) as id_medico ,
				( select distinct pf.nome 
					from medico m, profissional p, pessoa_fisica pf
					where m.id = agenda.id_medico and m.id_profissional =p.id and p.id_pessoa = pf.id_pessoa
				) as nome_medico ,
				COALESCE( (select distinct rp.usuario_executor
								from requisicao_procedimento rp , consulta c , 
									convenio_procedimento cp ,
									procedimento p , tipo_procedimento tp
								where
									c.id  = consulta.id  and rp.status_id = 2 and rp.id_consulta = c.id 
									and rp.id_convenio_procedimento = cp.id and rp.status_anamnese = 1
									and cp.id_procedimento = p.id and p.id_tipo_procedimento = tp.id 
									and tp.id in (4,5,6)
				),0) as id_assistente,
				( select distinct pf.nome
					from requisicao_procedimento rp , consulta c , convenio_procedimento cp ,
						procedimento p , tipo_procedimento tp , usuario u , pessoa_fisica pf
					where
						c.id  = consulta.id  and rp.status_id = 2  and rp.id_consulta = c.id
						and rp.id_convenio_procedimento = cp.id and rp.status_anamnese = 1  
						and cp.id_procedimento = p.id
						and p.id_tipo_procedimento  = tp.id and tp.id in (4,5,6)
						and rp.usuario_executor = u.id
						and u.id_pessoa = pf.id_pessoa
				) as nome_assistente
			FROM
				pet, raca, agendamento_pet, agendamento, agenda , consulta, procedimento
			where
				pet.id = :id_pet:
				and raca.id = pet.id_raca
				and pet.id = agendamento_pet.id_pet
				and agendamento_pet.id_agendamento = agendamento.id
				and agendamento.id_agenda = agenda.id
				and agendamento.id = consulta.id_agendamento
				and agendamento.id_procedimento = procedimento.id
		SQL;

		$binds = [ 
			'id_pet' => $id_pet
		];
		return $this->getDAOResponseFromPaginatedSelect( $binds, $pagination, $query_filter_collection, $query_order_collection, $sql,
			function (array $result_array): GeneralCollection {
				return ConsultaMapper::getFormularioListingVMCollectionFromArray( $result_array );
			} );

	}

	public function getConsultaListByPetIdByUnidadeID(int $idPet, int $idUnidade, ?Pagination $pagination, ?QueryFilterCollection $query_filter_collection,
			?QueryOrderCollection $query_order_collection = null): DAOResponse {

		$sql = $this->getSqlConsultaUnidade( $idUnidade );
		$binds = $this->getBindsConsultaPorUnidade( $idPet, $idUnidade );

		// $sql = <<<SQL
		// SELECT
		// agenda.id as id_agenda, agenda.id_unidade , agendamento.id as id_agendamento,
		// agendamento.cancelado_em as status, agendamento.id_requisicao ,
		// (select rp2.status_id from requisicao_procedimento rp2 where rp2.id = agendamento.id_requisicao ) as req_st,
		// (case
		// when (select rp2.status_id from requisicao_procedimento rp2 where rp2.id = agendamento.id_requisicao ) ='5' then 'Anamnse Adicional'
		// when (select rp2.status_id from requisicao_procedimento rp2 where rp2.id = agendamento.id_requisicao ) = '2' then 'Anamnse Normal'
		// when agendamento.id_requisicao is null then ''
		// end) as tipo_anamnese,
		// consulta.id as id_consulta, procedimento.id as id_procedimento,
		// procedimento.descricao as procedimento, agenda.data as data,
		// agenda.hora_inicio as hora_inicio, agenda.hora_final as hora_fim,
		// consulta.titulo as consulta_titulo, consulta.descricao as consulta_descricao,
		// pet.id as id_pet, pet.nome as nome_pet, pet.id_raca as id_raca, raca.nome as nome_raca,
		// COALESCE (agenda.id_medico,0) as id_medico ,
		// ( select distinct pf.nome
		// from medico m, profissional p, pessoa_fisica pf
		// where m.id = agenda.id_medico and m.id_profissional =p.id
		// and p.id_pessoa = pf.id_pessoa
		// ) as nome_medico ,
		// COALESCE(
		// (select distinct rp.usuario_executor
		// from requisicao_procedimento rp , consulta c ,
		// convenio_procedimento cp , procedimento p , tipo_procedimento tp
		// where
		// c.id = consulta.id and rp.status_id = 2 and rp.id_consulta = c.id
		// and rp.id_convenio_procedimento = cp.id and rp.status_anamnese = 1
		// and cp.id_procedimento = p.id and p.id_tipo_procedimento = tp.id
		// and tp.id in (4,5)
		// ),0
		// ) as id_assistente,
		// ( select distinct pf.nome
		// from requisicao_procedimento rp , consulta c , convenio_procedimento cp ,
		// procedimento p , tipo_procedimento tp , usuario u , pessoa_fisica pf
		// where
		// c.id = consulta.id and rp.status_id = 2 and rp.id_consulta = c.id
		// and rp.id_convenio_procedimento = cp.id and rp.status_anamnese = 1
		// and cp.id_procedimento = p.id
		// and p.id_tipo_procedimento = tp.id and tp.id in (4,5)
		// and rp.usuario_executor = u.id
		// and u.id_pessoa = pf.id_pessoa
		// ) as nome_assistente
		// FROM
		// pet, raca, agendamento_pet, agendamento, agenda , consulta, procedimento
		// where
		// pet.id = :id_pet:
		// and raca.id = pet.id_raca
		// and pet.id = agendamento_pet.id_pet
		// and agendamento_pet.id_agendamento = agendamento.id
		// and agendamento.id_agenda = agenda.id
		// and agenda.id_unidade = :id_unidade:
		// and agendamento.id = consulta.id_agendamento
		// and agendamento.id_procedimento = procedimento.id
		// SQL;

		// $binds = [
		// 'id_pet' => $idPet,
		// 'id_unidade' => $idUnidade
		// ];
		return $this->getDAOResponseFromPaginatedSelect( $binds, $pagination, $query_filter_collection, $query_order_collection, $sql,
			function (array $result_array): GeneralCollection {
				return ConsultaMapper::getFormularioListingVMCollectionFromArray( $result_array );
			} );

	}

	# ---------------------------------------------------------------------------------------------------------------#
	public function getConsultaByMedicoList(int $id_medico, ?Pagination $pagination, ?QueryFilterCollection $query_filter_collection,
			?QueryOrderCollection $query_order_collection = null): DAOResponse {

		$sql = '
            SELECT
                prontuario.id_paciente as id_paciente,
                pessoa_fisica.nome as nome,
                pessoa_fisica.cpf as cpf,
                usuario.email as email,
                endereco.numero as numero,
                endereco.complemento as complemento,
                endereco.referencias as referencias,
                cep.cep as cep,
                cep.cidade as cidade,
                cep.estado as estado,
                cep.bairro as bairro,
                cep.logradouro as logradouro
            FROM 
                 prontuario
                 INNER JOIN paciente ON paciente.id = prontuario.id_paciente
                 INNER JOIN pessoa ON paciente.id_pessoa = pessoa.id
                 INNER JOIN endereco ON endereco.id = pessoa.id_endereco
                 INNER JOIN cep ON cep.id = endereco.cep
                 INNER JOIN pessoa_fisica ON pessoa_fisica.id_pessoa = pessoa.id
                 INNER JOIN usuario ON usuario.id_pessoa = pessoa.id
            WHERE 
                  prontuario.id_medico = 1
        ';

		$binds = [ 
			'id_medico' => $id_medico
		];
		return $this->getDAOResponseFromPaginatedSelect( $binds, $pagination, $query_filter_collection, $query_order_collection, $sql,
			function (array $result_array): GeneralCollection {
				return ConsultaMapper::getConsultasByMedicoVMCollectionFromArray( $result_array );
			} );

	}

	# -------------------------------------------------------------------------------------------------------------------------------#
	public function persistConsultaUpdateVM(int $id_consulta, ConsultaUpdateViewModel $consulta_registration_vm): DAOResponse {

		$dao_response = new DAOResponse();
		$log_service = new LogService();
		$resposta_formulario_model = new RespostaFormularioModel();
		try {
			$this->db->transStart();
			$consulta = $this->persistConsultaByConsultaUpdateVM( $id_consulta, $consulta_registration_vm );
			$insert_respostas = $this->persistRespostasUpdate( $id_consulta, $consulta_registration_vm );
			// $insert_decimal = $this->persistRespostaNumericaDecimalUpdate($id_consulta, $consulta_registration_vm);
			// $insert_inteira = $insert_decimal && $this->persistRespostaNumericaInteiraUpdate($id_consulta, $consulta_registration_vm);
			// $insert_texto = $insert_inteira && $this->persistRespostaTextualUpdate($id_consulta, $consulta_registration_vm);
			// $insert_escolha_opcao = $insert_texto && $this->persistRespostaEscolhaOpcaoUpdate($id_consulta, $consulta_registration_vm);
			$error = $this->db->error();

			if ($error && $error ['code']) {
				$this->setDatabaseErrorsForConsultaRegistration( $dao_response, $error );
			} else if ($insert_respostas) {
				$this->db->transComplete();
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
			} else {
				$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			}
		} catch ( Exception $exception ) {
			$log_service->log_error( $exception->getCode(), $exception->getMessage(), [ ] );
			$this->setDatabaseErrorsForConsultaRegistration( $dao_response, $this->db->error() );
		}
		return $dao_response;

	}

	private function persistConsultaByConsultaUpdateVM(int $id_consulta, ConsultaUpdateViewModel $consulta_registration_vm): bool {

		$consulta_model = new ConsultaModel();
		$consulta = ConsultaMapper::getConsultaByConsultaUpdateVM( $consulta_registration_vm );
		$sucess_update = $consulta_model->updateConsultaByID( $id_consulta, $consulta );
		return $sucess_update;

	}

	private function persistRespostasUpdate(int $id_consulta, ConsultaUpdateViewModel $consulta_registration_vm): bool {

		$sucess_update = true;
		$list_resposta = $consulta_registration_vm->getRespostas();

		foreach ( $list_resposta as $row ) {
			$id_resposta_formulario = $this->getRespostaFormularioId( $row ['id_pergunta'], $id_consulta );

			// $resposta = ConsultaMapper::getRespostaNumericaByConsultaUpdateVM($row, $id_resposta_formulario);

			$respostaModel = null;
			switch ($row ['id_tipo_pergunta']) {
				case 1 :
				case 2 :
					$respostaModel = new RespostaTextualModel();
					break;
				case 3 :
				case 4 :
					$respostaModel = new RespostaEscolhaOpcaoModel();
			}
			$sucess_update = $respostaModel->updateResposta( $row, $id_resposta_formulario );
		}
		return $sucess_update;

	}

	private function persistRespostaNumericaDecimalUpdate(int $id_consulta, ConsultaUpdateViewModel $consulta_registration_vm): bool {

		$sucess_update = true;
		$consulta_model = new RespostaNumericaDecimalModel();
		$list_resposta = $consulta_registration_vm->getRespostaNumericaDecimalCollection();
		foreach ( $list_resposta->toArray() as $row ) {
			$id_resposta_formulario = $this->getRespostaFormularioId( $row ['id_pergunta'], $id_consulta );
			$resposta_numerica = ConsultaMapper::getRespostaNumericaByConsultaUpdateVM( $row, $id_resposta_formulario );
			$sucess_update = $consulta_model->updateRespostaNumericaDecimalCollection( $resposta_numerica, $id_resposta_formulario );
		}
		return $sucess_update;

	}

	private function persistRespostaNumericaInteiraUpdate(int $id_consulta, ConsultaUpdateViewModel $consulta_registration_vm): bool {

		$sucess_update = true;
		$consulta_model = new RespostaNumericaInteiraModel();
		$list_resposta = $consulta_registration_vm->getRespostaNumericaInteiraCollection();
		foreach ( $list_resposta->toArray() as $row ) {
			$id_resposta_formulario = $this->getRespostaFormularioId( $row ['id_pergunta'], $id_consulta );
			$resposta_numerica = ConsultaMapper::getRespostaInteiraByConsultaUpdateVM( $row, $id_resposta_formulario );
			$sucess_update = $consulta_model->updateRespostaNumericaInteiraCollection( $resposta_numerica, $id_resposta_formulario );
		}
		return $sucess_update;

	}

	private function persistRespostaTextualUpdate(int $id_consulta, ConsultaUpdateViewModel $consulta_registration_vm): bool {

		$sucess_update = true;
		$consulta_model = new RespostaTextualModel();
		$list_resposta = $consulta_registration_vm->getRespostaTextualCollection();
		foreach ( $list_resposta->toArray() as $row ) {
			$id_resposta_formulario = $this->getRespostaFormularioId( $row ['id_pergunta'], $id_consulta );
			$resposta_numerica = ConsultaMapper::getRespostaTextualByConsultaUpdateVM( $row, $id_resposta_formulario );
			$sucess_update = $consulta_model->updateRespostaTextualCollection( $resposta_numerica, $id_resposta_formulario );
		}
		return $sucess_update;

	}

	private function persistRespostaEscolhaOpcaoUpdate(int $id_consulta, ConsultaUpdateViewModel $consulta_registration_vm): bool {

		$sucess_update = true;
		$consulta_model = new RespostaEscolhaOpcaoModel();
		$list_resposta = $consulta_registration_vm->getRespostaEscolhaOpcaoCollection();
		foreach ( $list_resposta->toArray() as $row ) {
			$id_resposta_formulario = $this->getRespostaFormularioId( $row ['id_pergunta'], $id_consulta );
			$resposta_numerica = ConsultaMapper::getRespostaOptionByConsultaUpdateVM( $row, $id_resposta_formulario );
			$sucess_update = $consulta_model->updateRespostaEscolhaOpcaoCollection( $resposta_numerica, $id_resposta_formulario );
		}
		return $sucess_update;

	}

	# -------------------------------------------------------------------------------------------------------------#
	public function getRespostaFormularioId(int $id_pergunta, int $id_consulta): int {

		$sql = '
            SELECT
                resposta_formulario.id
            FROM 
                 resposta_formulario
            WHERE 
                resposta_formulario.id_pergunta = :id_pergunta:
				and resposta_formulario.id_consulta = :id_consulta:
        ';

		$binds = [ 
			'id_pergunta' => $id_pergunta,
			'id_consulta' => $id_consulta
		];
		$query = $this->db->query( $sql, $binds );
		$result_array = $query->getResultArray();
		return (( int ) ($result_array [0] ['id']));

	}

	# ------------------------------------------------------------------------------------------------------------------#
	public function getConsultaDetailsByConsultaID(int $id_consulta): DAOResponse {

		$sql = <<<SQL
			select distinct
				c.id as consulta_id, c.titulo as titulo_consulta, c.descricao as descricao_consulta,
				f.id as formulario_id, f.titulo as formulario_titulo, f.descricao as formulario_descricao,
				f.id_medico as formulario_id_medico, f.ativo as formulario_ativo,
				p.id as pergunta_id, p.id_tipo_pergunta as pergunta_id_tipo_pergunta,
				p.obrigatorio as pergunta_obrigatorio, p.ativo as pergunta_ativo, p.ordem as pergunta_ordem,
				p.texto_pergunta as pergunta_texto_pergunta,
				opcao_pergunta.id as opcao_pergunta_id,opcao_pergunta.descricao as opcao_pergunta_descricao,
				opcao_pergunta.id_pergunta as opcao_pergunta_id_pergunta
				, '' as resposta_pergunta_textual
				, '' as resposta_pergunta_opcao
				, '' as resposta_pergunta_inteira
				, '' as resposta_pergunta_decimal
			    ,  COALESCE(rp.usuario_executor,0) as usuario_executor_exame
			    , (select a2.id_medico from consulta c 
					inner join agendamento a on c.id_agendamento = a.id  
					inner join agenda a2 on a.id_agenda = a2.id 
					where c.id = :id_consulta:) as id_medico_consulta
			    , (select u.id 
					from medico m , profissional p, pessoa p2, usuario u ,usuario_perfil up
					where
						m.id = id_medico_consulta
						and m.id_profissional = p.id
						and p.id_pessoa = p2.id
						and p2.id = u.id_pessoa
						and u.id = up.id_usuario
						and up.id_perfil = 2 ) as usuario_medico_id
			from
				consulta c  LEFT JOIN requisicao_procedimento rp ON rp.id_consulta = c.id,
				formulario f,
				agendamento ag,
				pergunta p  LEFT OUTER JOIN opcao_pergunta ON p.id = opcao_pergunta.id_pergunta
			where
				c.id = :id_consulta:
				and c.id_agendamento = ag.id
				and c.id_formulario = f.id
				and p.id_formulario = f.id
		SQL;
		$binds = [ 
			'id_consulta' => $id_consulta
		];
		$query = $this->db->query( $sql, $binds );
		$result_array = $query->getResultArray();
		$registros = count( $result_array );
		for($i = 0; $i < $registros; $i++) {
			if (($result_array [$i] ['pergunta_id_tipo_pergunta'] == "2") || ($result_array [$i] ['pergunta_id_tipo_pergunta'] == "1")) {

				$sql_2 = ' select id from resposta_formulario ';
				$sql_2 .= " where id_consulta = :id_consulta: and id_pergunta= :id_pergunta:";

				$id_pergunta = $result_array [$i] ['pergunta_id'];

				$binds_2 = [ 
					'id_consulta' => $id_consulta,
					'id_pergunta' => $id_pergunta
				];
				$query_2 = $this->db->query( $sql_2, $binds_2 );
				$result_2_array = $query_2->getResultArray();
				$id_resposta = $result_2_array [0] ['id'];

				$sql_3 = 'select id , resposta as resposta,id_resposta_formulario ';
				$sql_3 .= ' from resposta_textual ';
				$sql_3 .= ' where id_resposta_formulario = :id_resposta:';
				$binds_3 = [ 
					'id_resposta' => $id_resposta
				];
				$query_3 = $this->db->query( $sql_3, $binds_3 );
				$result_3_array = $query_3->getResultArray();
				$resposta = $result_3_array [0] ['resposta'];

				$result_array [$i] ['resposta_pergunta_textual'] = $resposta;
			}
		}

		$dao_response = new DAOResponse();
		if (count( $result_array )) {
			$formulario_details_vm = ConsultaMapper::getConsultaDetailsVMFromArray( $result_array, $id_consulta );
			$dao_response->setData( $formulario_details_vm );
			$dao_response->setStatus( DAOResponseInterface::SUCESS );
		} else {
			$dao_response->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
		}
		return $dao_response;

	}

	public function getArrayRespostaOptions(int $id_pergunta, int $id_consulta): array {

		$sql = "SELECT
                resposta_escolha_opcao.id_opcao_pergunta as resposta_opcao
            FROM
				consulta
				LEFT JOIN resposta_formulario ON resposta_formulario.id_consulta = consulta.id
				LEFT JOIN resposta_escolha_opcao ON resposta_escolha_opcao.id_resposta_formulario = resposta_formulario.id
				LEFT JOIN pergunta ON pergunta.id = resposta_formulario.id_pergunta
			WHERE 
            	resposta_formulario.id_consulta = :id_consulta: AND
            	pergunta.id =" . $id_pergunta;
		$binds = [ 
			'id_consulta' => $id_consulta
		];
		$query = $this->db->query( $sql, $binds );
		$result_array = $query->getResultArray();

		return $result_array;

	}

	# -----------------------------------------------------------------------------------------------------------------#
	# LOCAIS NECESSÁRIOS PARA MANTER O ENDPOINT DE CONSULTA DE EXAMES #
	public function registerConsultaRequisicao(ConsultaRegistrationViewModel $consulta_registration_vm, array $data_post): DAOResponse {

		$dao_response = new DAOResponse();
		$log_service = new LogService();
		$resposta_formulario_model = new RespostaFormularioModel();
		try {
			$this->db->transStart();
			$consulta = $this->persistConsultaByConsultaRegistrationVM( $consulta_registration_vm );
			$prontuario = $this->persistProntuarioByConsultaRegistrationVM( $consulta_registration_vm );
			$insert_decimal = $this->persistRespostaNumericaDecimal( $consulta_registration_vm, $consulta, $resposta_formulario_model );
			$insert_inteira = $insert_decimal && $this->persistRespostaNumericaInteira( $consulta_registration_vm, $consulta, $resposta_formulario_model );
			$insert_texto = $insert_inteira && $this->persistRespostaTextual( $consulta_registration_vm, $consulta, $resposta_formulario_model );
			$insert_escolha_opcao = $insert_texto && $this->persistRespostaEscolhaOpcao( $consulta_registration_vm, $consulta, $resposta_formulario_model );

			// ==============================================================================================
			// Insertar os dados da anamnese na requisição
			// ==============================================================================================

			$usuario_executor = UsuarioLogado::getUsuarioId();

			if ($data_post ['id_requisicao_procedimento']) {
				$sql_requisicao = <<<SQL
				    UPDATE 
				        requisicao_procedimento 
				    SET 
				        status_id = 2,
				        id_consulta = :id_consulta:,
				        data_execucao = :data_execucao:,
				        hora_execucao = :hora_execucao:,
				        status_anamnese = 1,
				        id_consulta_exame = :id_consulta_exame:,
				        usuario_executor = :usuario_executor:
				    WHERE id = :requisicao_procedimento_id:
				SQL;
				$binds = [ 
					'id_consulta' => $consulta->getId(),
					'usuario_executor' => $usuario_executor,
					'data_execucao' => date( 'Y-m-d' ),
					'hora_execucao' => date( 'H:i:s' ),
					'requisicao_procedimento_id' => $data_post ['id_requisicao_procedimento'],
					'id_consulta_exame' => $consulta->getId()
				];
				$this->db->query( $sql_requisicao, $binds );
			}

			$error = $this->db->error();
			$dao_response->setData( [ 
				"consulta_id" => $consulta->getId()
			] );
			if ($error && $error ['code']) {

				$this->setDatabaseErrorsForConsultaRegistration( $dao_response, $error );
			} else if ($insert_escolha_opcao) {
				$this->db->transComplete();
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
			} else {
				$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			}
		} catch ( Exception $exception ) {
			$this->db->transRollback();
			$log_service->log_error( $exception->getCode(), $exception->getMessage(), [ ] );
			$this->setDatabaseErrorsForConsultaRegistration( $dao_response, $this->db->error() );
		}
		return $dao_response;

	}

	public function registerConsultaMultipleRequisicao(ConsultaRegistrationViewModel $consulta_registration_vm, array $data_post, $id_requisicao_procedimento): DAOResponse {

		$dao_response = new DAOResponse();
		$log_service = new LogService();
		$resposta_formulario_model = new RespostaFormularioModel();
		try {
			$this->db->transStart();
			$consulta = $this->persistConsultaByConsultaRegistrationVM( $consulta_registration_vm );
			$prontuario = $this->persistProntuarioByConsultaRegistrationVM( $consulta_registration_vm );
			$insert_decimal = $this->persistRespostaNumericaDecimal( $consulta_registration_vm, $consulta, $resposta_formulario_model );
			$insert_inteira = $insert_decimal && $this->persistRespostaNumericaInteira( $consulta_registration_vm, $consulta, $resposta_formulario_model );
			$insert_texto = $insert_inteira && $this->persistRespostaTextual( $consulta_registration_vm, $consulta, $resposta_formulario_model );
			$insert_escolha_opcao = $insert_texto && $this->persistRespostaEscolhaOpcao( $consulta_registration_vm, $consulta, $resposta_formulario_model );

			// ==============================================================================================
			// Insertar os dados da anamnese na requisição
			// ==============================================================================================

			$usuario_executor = UsuarioLogado::getUsuarioId();

			if ($id_requisicao_procedimento) {
				$sql_requisicao = <<<SQL
				    UPDATE 
				        requisicao_procedimento 
				    SET 
				        status_id = 2,
				        id_consulta = :id_consulta:,
				        data_execucao = :data_execucao:,
				        hora_execucao = :hora_execucao:,
				        status_anamnese = 1,
				        id_consulta_exame = :id_consulta_exame:,
				        usuario_executor = :usuario_executor:
				    WHERE id = :requisicao_procedimento_id:
				SQL;
				$binds = [ 
					'id_consulta' => $consulta->getId(),
					'usuario_executor' => $usuario_executor,
					'data_execucao' => date( 'Y-m-d' ),
					'hora_execucao' => date( 'H:i:s' ),
					'requisicao_procedimento_id' => $id_requisicao_procedimento,
					'id_consulta_exame' => $consulta->getId()
				];
				$this->db->query( $sql_requisicao, $binds );
			}

			$error = $this->db->error();
			$dao_response->setData( [ 
				"consulta_id" => $consulta->getId()
			] );
			if ($error && $error ['code']) {

				$this->setDatabaseErrorsForConsultaRegistration( $dao_response, $error );
			} else if ($insert_escolha_opcao) {
				$this->db->transComplete();
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
			} else {
				$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			}
		} catch ( Exception $exception ) {
			$this->db->transRollback();
			$log_service->log_error( $exception->getCode(), $exception->getMessage(), [ ] );
			$this->setDatabaseErrorsForConsultaRegistration( $dao_response, $this->db->error() );
		}
		return $dao_response;

	}

	public function registerAgendamentoBaseRequisicao(array $data_post) {

		$dao_response = new DAOResponse();
		$log_service = new LogService();
		try {
			$this->db->transStart();
			$detalhes_requisicao = $this->buscaDetalhesRequisicao( $data_post ['id_requisicao_procedimento'] );
			$agenda = $this->insertAgendaRequisicaoProcedimento( $data_post, $detalhes_requisicao [0] ['id_unidade'] );
			$agendamento = $this->insertAgendamentoRequisicaoProcedimento( $agenda, $detalhes_requisicao [0] ['id_cliente'],
				$detalhes_requisicao [0] ['id_paciente'], $detalhes_requisicao [0] ['id_procedimento'], $data_post ['id_requisicao_procedimento'] );
			$agendamento_pet = $this->insertAgendamentoPet( $agendamento, $detalhes_requisicao [0] ['id_pet'] );
			$this->db->transComplete();
			return $agendamento;
		} catch ( Exception $exception ) {
			$this->db->transRollback();
			$log_service->log_error( $exception->getCode(), $exception->getMessage(), [ ] );
			return 0;
		}

	}

	public function registerAgendamentoMultipleBaseRequisicao(array $data_post, $id_requisicao_procedimento, $key) {

		$dao_response = new DAOResponse();
		$log_service = new LogService();
		try {
			$this->db->transStart();
			$detalhes_requisicao = $this->buscaDetalhesRequisicao( $id_requisicao_procedimento );
			$agenda = $this->insertAgendaRequisicaoMultipleProcedimento( $data_post, $detalhes_requisicao [0] ['id_unidade'], $key );
			$agendamento = $this->insertAgendamentoRequisicaoProcedimento( $agenda, $detalhes_requisicao [0] ['id_cliente'],
				$detalhes_requisicao [0] ['id_paciente'], $detalhes_requisicao [0] ['id_procedimento'], $id_requisicao_procedimento );
			$agendamento_pet = $this->insertAgendamentoPet( $agendamento, $detalhes_requisicao [0] ['id_pet'] );
			$this->db->transComplete();
			return $agendamento;
		} catch ( Exception $exception ) {
			$this->db->transRollback();
			$log_service->log_error( $exception->getCode(), $exception->getMessage(), [ ] );
			return 0;
		}

	}

	public function buscaDetalhesRequisicao(int $id_requisicao) {

		$sql = "
            SELECT 
                rp.id as id_requisicao_procedimento
                ,rp.id_pet as id_pet
                ,rp.id_consulta as id_consulta
                ,cp.id_procedimento as id_procedimento
                ,cp.id_unidade as id_unidade
                ,pc.id_cliente
                ,p.id_tipo_procedimento 
                ,p2.id as id_paciente
            FROM 
                requisicao_procedimento rp, 
                convenio_procedimento cp, 
                pet_cliente pc,
                procedimento p,
                cliente c,
                paciente p2
            WHERE 
                rp.id_convenio_procedimento = cp.id and 
                rp.id_pet = pc.id_pet and 
                cp.id_procedimento = p.id AND 
                c.id = pc.id_cliente  and
                p2.id_pessoa = c.id_pessoa and	
                rp.id = :id_requisicao:

        ";
		$binds = [ 
			'id_requisicao' => $id_requisicao
		];
		$query = $this->db->query( $sql, $binds );
		$result_array = $query->getResultArray();
		return $result_array;

	}

	public function insertAgendaRequisicaoProcedimento(array $data_post, $id_unidade) {

		$today = DateUtils::today();
		$day = date( "Y-m-d" );
		$time = date( "H:i" );
		$timesecond = date( "H:i:s" );
		$executor = UsuarioLogado::getUsuarioId();
		$id_assistente = null;

		$busca_assistente = 'select a.id as id from usuario u 
             inner join profissional p2 on p2.id_pessoa = u.id_pessoa
             inner join assistente a on p2.id = a.id_profissional
             where u.id = :executor:
        ';

		$value_assistente = [ 
			'executor' => $executor
		];

		$resultAssistente = $this->db->query( $busca_assistente, $value_assistente )
			->getResult();
		$id_assistente = $resultAssistente [0]->id != null ? ( int ) $resultAssistente [0]->id : 'NULL';

		$sql = 'INSERT INTO agenda (
                    codigo,
                    id_medico,
                    id_unidade,
                    `data`,
                    `hora_inicio`,
                    `hora_final`,
                    `id_tipo_procedimento`,
                    `adicionado_por`,
                    `criado_em`,
                    `id_assistente`
                ) VALUES ()
        ';

		$values = "(
            'A-{$id_assistente}-{$id_unidade}-{$day}-{$timesecond}',
            NULL,
            '{$id_unidade}',   
            '{$day}',   
            '{$time}',   
            '{$time}',   
            1,   
            '{$executor}',
            '{$today}',
            '{$id_assistente}'
        )";

		$sql = str_replace( 'VALUES ()', "VALUES $values;", $sql );
		$query = $this->db->query( $sql );
		return $query->connID->insert_id;

	}

	public function insertAgendaRequisicaoMultipleProcedimento(array $data_post, $id_unidade, $key) {

		$assistente_service = new AssistenteService();

		$today = DateUtils::today();
		$day = date( "Y-m-d" );
		$time = date( "H:i" );
		$timesecond = date( "H:i:s" );
		$dateTime = new DateTime( $timesecond );

		// Adiciona os segundos definidos à variável
		$dateTime->add( new DateInterval( 'PT' . $key . 'S' ) );

		$usr = UsuarioLogado::getUsuarioId();

		$id_assistente = $assistente_service->getAssistenteIDFromUsuarioID( $usr );
		// Obtém o tempo modificado formatado como HH:mm:ss
		$timesecond_modificado = $dateTime->format( 'H:i:s' );

		$sql = 'INSERT INTO agenda (
                    codigo,
                    id_medico,
                    id_unidade,
                    `data`,
                    `hora_inicio`,
                    `hora_final`,
                    `id_tipo_procedimento`,
                    `adicionado_por`,
                    `criado_em`,
					id_assistente
                ) VALUES ()
        ';

		$values = "(
            'A-{$id_assistente}-{$id_unidade}-{$day}-{$timesecond_modificado}',
            NULL,
            '{$id_unidade}',   
            '{$day}',   
            '{$time}',   
            '{$time}',   
            1,   
            '{$usr}',   
            '{$today}',
			'{$id_assistente}'
        )";

		$sql = str_replace( 'VALUES ()', "VALUES $values;", $sql );
		$query = $this->db->query( $sql );
		return $query->connID->insert_id;

	}

	public function insertAgendamentoRequisicaoProcedimento($id_agenda, $id_cliente, $id_paciente, $id_procedimento, $id_requisicao) {

		$today = DateUtils::today();
		$day = date( "Y-m-d" );
		$time = date( "H:i" );

		$sql = 'INSERT INTO agendamento
                (id_agenda, id_cliente, id_paciente, id_procedimento, codigo, cancelado_em, adicionado_por, alterado_por, alterado_em, criado_em, atrasado, id_requisicao)
                VALUES ()
        ';
		$values = "(
            '{$id_agenda}', 
            '{$id_cliente}', 
            '{$id_paciente}', 
            '{$id_procedimento}', 
            '{$id_agenda}', 
            NULL, 
            NULL, 
            NULL, 
            NULL, 
            '{$today}', 
            '0',
            '{$id_requisicao}'
        )";

		$sql = str_replace( 'VALUES ()', "VALUES $values;", $sql );
		$query = $this->db->query( $sql );
		return $query->connID->insert_id;

	}

	public function insertAgendamentoPet(int $id_agendamento, int $id_pet) {

		$sql = 'INSERT INTO agendamento_pet
                (id_agendamento, id_pet)
                VALUES ()
        ';
		$values = "(
            '{$id_agendamento}', 
            '{$id_pet}'
        )";

		$sql = str_replace( 'VALUES ()', "VALUES $values;", $sql );
		;
		$query = $this->db->query( $sql );
		return $query->connID->insert_id;

	}

	public function registerConsultaEndpointRequisicao(int $id_agendamento) {

		$usuario = UsuarioLogado::getUsuarioId();
		$today = DateUtils::today();

		$sql = 'INSERT INTO consulta
                (adicionado_por, alterado_por, criado_em, alterado_em, id_agendamento, id_formulario, titulo, descricao)
                VALUES ()

        ';
		$values = "(
            '{$usuario}', 
            '{$usuario}',
            '{$today}',
            '{$today}',
            '{$id_agendamento}',
            NULL,
            'Marcação de atendimento',
            'Marcação de atendimento'
        )";

		$sql = str_replace( 'VALUES ()', "VALUES $values;", $sql );
		;
		$query = $this->db->query( $sql );
		return $query->connID->insert_id;

	}

	public function updateRequisicaoProcedimento(int $id_requisicao_procedimento, $id_consulta) {

		$sql_requisicao = <<<SQL
		    UPDATE 
		        requisicao_procedimento 
		    SET 
		        id_consulta = :id_consulta:
		    WHERE id = :requisicao_procedimento_id:
		SQL;
		$binds = [ 
			'id_consulta' => $id_consulta,
			'requisicao_procedimento_id' => $id_requisicao_procedimento
		];
		$this->db->query( $sql_requisicao, $binds );

	}

	public function registerConsultaAnamneseAdicional(ConsultaRegistrationViewModel $consulta_registration_vm, array $data_post): DAOResponse {

		$dao_response = new DAOResponse();
		$log_service = new LogService();
		$resposta_formulario_model = new RespostaFormularioModel();
		try {
			$this->db->transStart();
			$consulta = $this->persistConsultaByConsultaRegistrationVM( $consulta_registration_vm );
			$prontuario = $this->persistProntuarioByConsultaRegistrationVM( $consulta_registration_vm );
			$insert_decimal = $this->persistRespostaNumericaDecimal( $consulta_registration_vm, $consulta, $resposta_formulario_model );
			$insert_inteira = $insert_decimal && $this->persistRespostaNumericaInteira( $consulta_registration_vm, $consulta, $resposta_formulario_model );
			$insert_texto = $insert_inteira && $this->persistRespostaTextual( $consulta_registration_vm, $consulta, $resposta_formulario_model );
			$insert_escolha_opcao = $insert_texto && $this->persistRespostaEscolhaOpcao( $consulta_registration_vm, $consulta, $resposta_formulario_model );

			// ==============================================================================================
			// Altera a requisiçao para executado e seta os id do medico de consulta
			// ==============================================================================================

			$id_requisicao_procedimento = $data_post ['id_requisicao_procedimento'];

			$sql_getIdMedico = <<<SQL
			    select
			        agenda.id_medico
			    from agenda, agendamento
			    where
			        agendamento.id_agenda = agenda.id and
			        agendamento.id = :id_agendamento:
			SQL;
			$binds = [ 
				'id_agendamento' => $consulta_registration_vm->getIdAgendamento()
			];
			$id_medico = $this->db->query( $sql_getIdMedico, $binds )
				->getResultArray();

			if ($id_requisicao_procedimento) {

				$sql_requisicao = <<<SQL
				update
				    requisicao_procedimento
				set
				    status_id = :id_status:,
				    id_medico = :id_medico:,
				    id_consulta = :id_consulta:,
				    data_execucao = :data_execucao:,
				    hora_execucao = :hora_execucao:
				    where id = :requisicao_procedimento_id:
						and status_id = :idstatus:
				SQL;
				$binds = [ 
					'id_status' => REQUISICAO_STATUS_EXECUTADO_ATD_CONTINUADO,
					'idstatus' => REQUISICAO_STATUS_CRIADO_ATD_CONTIUADO,
					'id_medico' => $id_medico [0] ['id_medico'],
					'id_consulta' => $consulta->getId(),
					'data_execucao' => date( 'Y-m-d' ),
					'hora_execucao' => date( 'H:i:s' ),
					'requisicao_procedimento_id' => $id_requisicao_procedimento
				];
				$conn_req_exec = db_connect();
				$conn_req_exec->query( $sql_requisicao, $binds );
				$req_exec_affectrow = $conn_req_exec->affectedRows();
				$rec_exec_error = $conn_req_exec->error();
			}

			// ==============================================================================================
			// Fim do bloco de marcar como executado
			// ==============================================================================================

			$error = $this->db->error();
			$dao_response->setData( [ 
				"consulta_id" => $consulta->getId()
			] );
			if ($error && $error ['code']) {

				$this->setDatabaseErrorsForConsultaRegistration( $dao_response, $error );
			} else if ($insert_escolha_opcao) {
				$this->db->transComplete();
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
			} else {
				$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			}
		} catch ( Exception $exception ) {
			$log_service->log_error( $exception->getCode(), $exception->getMessage(), [ ] );
			$this->setDatabaseErrorsForConsultaRegistration( $dao_response, $this->db->error() );
		}
		return $dao_response;

	}

	public function getConsultaListByComandaID(int $comandaId): DAOResponse {

		$dao_response = new DAOResponse();
		$sql = <<<SQL
			SELECT
				agenda.id as id_agenda, agenda.id_unidade , agendamento.id as id_agendamento,
				agendamento.cancelado_em as status, consulta.id as id_consulta,
				procedimento.id as id_procedimento, procedimento.descricao as procedimento,
				agenda.data as data, agenda.hora_inicio as hora_inicio,	
				agenda.hora_final as hora_fim, consulta.titulo as consulta_titulo,
				consulta.descricao as consulta_descricao, pet.id as id_pet, 
				pet.nome as nome_pet, pet.id_raca as id_raca, raca.nome as nome_raca,
				COALESCE (agenda.id_medico,0) as id_medico ,
				( select distinct pf.nome
					from medico m, profissional p, pessoa_fisica pf
					where
						m.id = agenda.id_medico
						and m.id_profissional = p.id
						and p.id_pessoa = pf.id_pessoa
				) as nome_medico ,
				COALESCE( (select distinct rp.usuario_executor
								from requisicao_procedimento rp , consulta c , 
									convenio_procedimento cp ,
									procedimento p , tipo_procedimento tp
								where
									c.id  = consulta.id  and rp.status_id = 2 and rp.id_consulta = c.id 
									and rp.id_convenio_procedimento = cp.id and rp.status_anamnese = 1
									and cp.id_procedimento = p.id and p.id_tipo_procedimento = tp.id 
									and tp.id in (4,5,6)
				),0) as id_assistente,
				( select distinct pf.nome
					from requisicao_procedimento rp , consulta c , convenio_procedimento cp ,
						procedimento p , tipo_procedimento tp , usuario u , pessoa_fisica pf
					where
						c.id  = consulta.id  and rp.status_id = 2  and rp.id_consulta = c.id
						and rp.id_convenio_procedimento = cp.id and rp.status_anamnese = 1  
						and cp.id_procedimento = p.id
						and p.id_tipo_procedimento  = tp.id and tp.id in (4,5,6)
						and rp.usuario_executor = u.id
						and u.id_pessoa = pf.id_pessoa
				) as nome_assistente
			FROM
				comanda, pet, raca, agendamento_pet, agendamento, agenda , consulta, procedimento
			where
				comanda.id = :id_comanda:
				and comanda.id_pet = pet.id
				and comanda.id_unidade = agenda.id_unidade
				and comanda.data_criada <= agenda.`data`
				and (comanda.data_fechada >= agenda.`data` or comanda.data_fechada = '1900-01-01')
				and raca.id = pet.id_raca
				and pet.id = agendamento_pet.id_pet
				and agendamento_pet.id_agendamento = agendamento.id
				and agendamento.id_agenda = agenda.id
				and agendamento.id = consulta.id_agendamento
				and agendamento.id_procedimento = procedimento.id	
		SQL;

		$binds = [ 
			'id_comanda' => $comandaId
		];

		$conn = db_connect();
		$result_array = $conn->query( $sql, $binds )
			->getResultArray();
		$errors = $conn->error();
		if ($errors ['code'] != 0) {
			$dao_response->setErrors( $errors );
			$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
		} else {
			// $list_result = array();
			// $list_result = ConsultaMapper::getFormularioListingVMCollectionFromArray( $result_array );
			$dao_response->setData( [ 
				'prontuarios' => $result_array
			] );
			$dao_response->setStatus( DAOResponseInterface::SUCESS );
		}

		return $dao_response;

	}

	public function auditRegisterExameMedicacaoAtendimento(array $data_post): DAOResponse {

		$titulo = 'titulo';
		$descricao = 'descricao';
		$adicionado_por = UsuarioLogado::getUsuarioId();
		$idFormulario = null;
		$idAgendamento = $data_post ['id_agendamento'];
		$criado_em = DateUtils::now();
		$alterado_em = $criado_em;

		$sql = <<<SQL
			insert into consulta 
			(adicionado_por,criado_em,alterado_em,id_agendamento,id_formulario,titulo,descricao) values
			(:adicionado_por:,:criado_em:,:alterado_em:,:id_agendamento:,:id_formulario:,:titulo:,:descricao:)
		SQL;

		$binds = [ 
			'adicionado_por' => $adicionado_por,
			'criado_em' => $criado_em,
			'alterado_em' => $alterado_em,
			'id_agendamento' => $idAgendamento,
			'id_formulario' => $idFormulario,
			'titulo' => $titulo,
			'descricao' => $descricao
		];

		$dao_response = new DAOResponse();
		$conn = db_connect();
		$conn->query( $sql, $binds )->numRows;
		$errors = $conn->error();
		if ($errors ['code'] != 0) {
			$dao_response->setErrors( $errors );
			$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
		} else {
			$affectRows = $conn->affectedRows();
			if ($affectRows == 0) {
				$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			} else {
				$newId = $conn->insertID();
				$dao_response->setData( [ 
					'id_consulta' => $newId
				] );
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
			}
		}

		return $dao_response;

	}

	private function getSqlConsultaUnidade(int $idUnidade) {

		$sql = '';
		if ($idUnidade != 24) {

			$sql = <<<SQL
				SELECT
					agenda.id as id_agenda, agenda.id_unidade , agendamento.id as id_agendamento,
					agendamento.cancelado_em as status, agendamento.id_requisicao ,
					(select rp2.status_id from requisicao_procedimento rp2 where rp2.id = agendamento.id_requisicao ) as req_st,
					(case
						when (select rp2.status_id from requisicao_procedimento rp2 where rp2.id = agendamento.id_requisicao ) ='5' then 'Anamnse Adicional'
						when (select rp2.status_id from requisicao_procedimento rp2 where rp2.id = agendamento.id_requisicao ) = '2' then 'Anamnse Normal'
						when agendamento.id_requisicao is null then ''
					end) as tipo_anamnese,
					consulta.id as id_consulta, procedimento.id as id_procedimento,
					procedimento.descricao as procedimento, agenda.data as data,
					agenda.hora_inicio as hora_inicio, agenda.hora_final as hora_fim,
					consulta.titulo as consulta_titulo, consulta.descricao as consulta_descricao,
					pet.id as id_pet, pet.nome as nome_pet, pet.id_raca as id_raca, raca.nome as nome_raca,
					COALESCE (agenda.id_medico,0) as id_medico ,
					( select distinct pf.nome
						from medico m, profissional p, pessoa_fisica pf
						where m.id = agenda.id_medico and m.id_profissional =p.id
							and p.id_pessoa = pf.id_pessoa
					) as nome_medico ,
					COALESCE(
						(select distinct rp.usuario_executor
							from requisicao_procedimento rp , consulta c ,
								convenio_procedimento cp ,	procedimento p , tipo_procedimento tp
							where
								-- c.id  = consulta.id  
								-- and rp.status_id = 2 
								rp.id_consulta = c.id
								and rp.id_convenio_procedimento = cp.id 
								-- and rp.status_anamnese = 1
								and cp.id_procedimento = p.id 
								and p.id_tipo_procedimento = tp.id
								and tp.id in (4,5,6,9)
								and rp.id = agendamento.id_requisicao 
						),0
					) as id_assistente,
					( select distinct pf.nome
						from requisicao_procedimento rp , consulta c , convenio_procedimento cp ,
							procedimento p , tipo_procedimento tp , usuario u , pessoa_fisica pf
						where
							-- c.id  = consulta.id  
							-- rp.status_id = 2  
							rp.id_consulta = c.id
							and rp.id_convenio_procedimento = cp.id 
							-- and rp.status_anamnese = 1
							and cp.id_procedimento = p.id
							and p.id_tipo_procedimento = tp.id and tp.id in (4,5,6,9)
							and rp.usuario_executor = u.id
							and u.id_pessoa = pf.id_pessoa
							and rp.id = agendamento.id_requisicao 
					) as nome_assistente
				FROM
					pet, raca, agendamento_pet, agendamento, agenda , consulta, procedimento
				where
					pet.id = :id_pet:
					and raca.id = pet.id_raca
					and pet.id = agendamento_pet.id_pet
					and agendamento_pet.id_agendamento = agendamento.id
					and agendamento.id_agenda = agenda.id
					and agenda.id_unidade = :id_unidade:
					and agendamento.id = consulta.id_agendamento
					and agendamento.id_procedimento = procedimento.id
			SQL;
		} else {
			$sql = <<<SQL
				SELECT
					agenda.id as id_agenda, agenda.id_unidade , agendamento.id as id_agendamento,
					agendamento.cancelado_em as status, agendamento.id_requisicao ,
					(select rp2.status_id from requisicao_procedimento rp2 where rp2.id = agendamento.id_requisicao ) as req_st,
					(case
						when (select rp2.status_id from requisicao_procedimento rp2 where rp2.id = agendamento.id_requisicao ) ='5' then 'Anamnse Adicional'
						when (select rp2.status_id from requisicao_procedimento rp2 where rp2.id = agendamento.id_requisicao ) = '2' then 'Anamnse Normal'
						when agendamento.id_requisicao is null then ''
					end) as tipo_anamnese,
					consulta.id as id_consulta, procedimento.id as id_procedimento,
					procedimento.descricao as procedimento, agenda.data as data,
					agenda.hora_inicio as hora_inicio, agenda.hora_final as hora_fim,
					consulta.titulo as consulta_titulo, consulta.descricao as consulta_descricao,
					pet.id as id_pet, pet.nome as nome_pet, pet.id_raca as id_raca, raca.nome as nome_raca,
					COALESCE (agenda.id_medico,0) as id_medico ,
					( select distinct pf.nome
						from medico m, profissional p, pessoa_fisica pf
						where m.id = agenda.id_medico and m.id_profissional =p.id
							and p.id_pessoa = pf.id_pessoa
					) as nome_medico ,
					COALESCE(
						(select distinct rp.usuario_executor
							from requisicao_procedimento rp , consulta c ,
								convenio_procedimento cp ,	procedimento p , tipo_procedimento tp
							where
								c.id  = consulta.id  and rp.status_id = 2 and rp.id_consulta = c.id
								and rp.id_convenio_procedimento = cp.id and rp.status_anamnese = 1
								and cp.id_procedimento = p.id and p.id_tipo_procedimento = tp.id
								and tp.id in (4,5,6)
						),0
					) as id_assistente,
					( select distinct pf.nome
						from requisicao_procedimento rp , consulta c , convenio_procedimento cp ,
							procedimento p , tipo_procedimento tp , usuario u , pessoa_fisica pf
						where
							c.id  = consulta.id  and rp.status_id = 2  and rp.id_consulta = c.id
							and rp.id_convenio_procedimento = cp.id and rp.status_anamnese = 1
							and cp.id_procedimento = p.id
							and p.id_tipo_procedimento = tp.id and tp.id in (4,5,6,9)
							and rp.usuario_executor = u.id
							and u.id_pessoa = pf.id_pessoa
					) as nome_assistente
				FROM
					pet, raca, agendamento_pet, agendamento, agenda , consulta, procedimento
				where
					pet.id = :id_pet:
					and raca.id = pet.id_raca
					and pet.id = agendamento_pet.id_pet
					and agendamento_pet.id_agendamento = agendamento.id
					and agendamento.id_agenda = agenda.id				
					and agendamento.id = consulta.id_agendamento
					and agendamento.id_procedimento = procedimento.id
			SQL;
		}

		return $sql;

	}

	private function getBindsConsultaPorUnidade(int $idPet, int $idUnidade) {

		$binds = [ ];

		if ($idUnidade != 24) {
			$binds = [ 
				'id_pet' => $idPet,
				'id_unidade' => $idUnidade
			];
		} else {
			$binds = [ 
				'id_pet' => $idPet
			];
		}

		return $binds;

	}

}
