<?php

namespace App\DAO;

use App\ChameFacil\UnidadeServiceCF;
use App\DAO\DAOResponse\DAOResponse;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\DAO\Pagination\Pagination;
use App\Entities\CEP\CEP;
use App\Entities\Endereco\Endereco;
use App\Entities\Pessoa\Pessoa;
use App\Entities\PessoaJuridica\PessoaJuridica;
use App\Entities\Unidade\Unidade;
use App\Mappers\UnidadeMapper;
use App\Models\CEPModel;
use App\Models\EnderecoModel;
use App\Models\PessoaJuridicaModel;
use App\Models\PessoaModel;
use App\Models\UnidadeModel;
use App\Utils\Collections\QueryFilterCollection;
use App\Utils\Collections\QueryOrderCollection;
use App\ViewModels\UnidadeUF\UnidadeUFRegistrationViewModel\UnidadeUFRegistrationViewModel;
use App\ViewModels\UnidadeUF\UnidadeUFUpdateViewModel\UnidadeUFUpdateViewModel;
use App\ViewModels\Unidade\UnidadeRegistrationViewModel\UnidadeRegistrationViewModel;
use App\ViewModels\Unidade\UnidadeUpdateViewModel\UnidadeUpdateViewModel;
use Exception;

class UnidadeDAO extends DAO {

	public function persistUnidadeRegistrationVM(UnidadeRegistrationViewModel $unidade_registration_vm): DAOResponse {

		$dao_response = new DAOResponse();
		$unidade_service_cf = new UnidadeServiceCF();
		try {
			$this->db->transStart();
			$cep = $this->persistCepFromUnidadeRegistrationVM( $unidade_registration_vm );
			$endereco = $this->persistEnderecoFromUnidadeRegistrationVM( $unidade_registration_vm, $cep );
			$pessoa = $this->persistPessoaFromUnidadeRegistrationVM( $unidade_registration_vm, $endereco );
			$pessoa_fisica = $this->persistPessoaJuridicaFromUnidadeRegistrationVM( $unidade_registration_vm, $pessoa );
			$unidade = $this->persistUnidadeFromUnidadeRegistrationVM( $unidade_registration_vm, $pessoa_fisica );

			$error = $this->db->error();
			if ($error && $error ['code']) {
				$this->setDatabaseErrorsForUnidadeRegistration( $dao_response, $error );
			} else {
				$unidade_edit_chamefacil = new UnidadeModel();
				$response_usuario = $unidade_service_cf->createUnidadeCf( $unidade_registration_vm );
				$unidade_edit_chamefacil->updateIdChameFacilByUnidadeID( $unidade->getId(), $response_usuario->Id );
				if ($response_usuario->Id > 0) {
					$dao_response->setStatus( DAOResponseInterface::SUCESS );
					$this->db->transComplete();
				} else {
					$this->setDatabaseErrorsForUnidadeRegistration( $dao_response, $error );
				}
			}
		} catch ( Exception $exception ) {
			$this->setDatabaseErrorsForUnidadeRegistration( $dao_response, $this->db->error() );
		}
		return $dao_response;

	}

	private function setDatabaseErrorsForUnidadeRegistration(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 persistCepFromUnidadeRegistrationVM(UnidadeRegistrationViewModel &$assistente_registration_vm): CEP {

		$cep_model = new CEPModel();
		$cep = UnidadeMapper::getCepFromUnidadeRegistrationVM( $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 persistEnderecoFromUnidadeRegistrationVM(UnidadeRegistrationViewModel &$unidade_registration_vm, CEP $cep): Endereco {

		$endereco_model = new EnderecoModel();
		$endereco = UnidadeMapper::getEnderecoFromUnidadeRegistrationVM( $unidade_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 persistPessoaFromUnidadeRegistrationVM(UnidadeRegistrationViewModel &$unidade_registration_vm, Endereco &$endereco): Pessoa {

		$pessoa_model = new PessoaModel();
		$pessoa = UnidadeMapper::getPessoaFromUnidadeRegistrationVM( $unidade_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 persistPessoaJuridicaFromUnidadeRegistrationVM(UnidadeRegistrationViewModel &$unidade_registration_vm, Pessoa &$pessoa): PessoaJuridica {

		$unidade_model = new PessoaJuridicaModel();
		$unidade = UnidadeMapper::getPessoaJuridicaFromUnidadeRegistrationVM( $unidade_registration_vm, $pessoa );
		$unidade_model->registerPessoaJuridica( $unidade );
		if (!$unidade->getId()) {
			throw new Exception( 'O cadastro de pessoa_juridica não teve êxito' );
		}
		return $unidade;

	}

	private function persistUnidadeFromUnidadeRegistrationVM(UnidadeRegistrationViewModel &$unidade_registration_vm, PessoaJuridica &$pessoa): Unidade {

		$unidade_model = new UnidadeModel();
		$unidade = UnidadeMapper::getUnidadeFromUnidadeRegistrationVM( $unidade_registration_vm, $pessoa );
		$unidade_model->registerUnidade( $unidade );
		if (!$unidade->getId()) {
			throw new Exception( 'O cadastro de unidade não teve êxito' );
		}
		return $unidade;

	}

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

		$sql = '
            SELECT 
            pessoa_juridica.id as pessoa_juridica_id
            ,pessoa_juridica.nome_fantasia as nome_fantasia
            ,pessoa_juridica.razao_social as razao_social 
            ,pessoa_juridica.cnpj as cnpj 
            ,pessoa.id as pessoa_id
            ,pessoa.telefone_1 as telefone_1
            ,pessoa.telefone_2 as telefone_2
            ,pessoa.observacao as observacao
            ,endereco.id as endereco_id
            ,cep.cep as cep
            ,endereco.numero as numero
            ,endereco.complemento as complemento
            ,endereco.referencias as referencias
            ,cep.id as cep_id 
            ,cep.bairro as bairro
            ,cep.logradouro as logradouro
            ,cep.cidade as cidade
            ,cep.estado as estado
            ,unidade.descricao
            ,unidade.telemedicina
            ,unidade.id as unidade_id
			,unidade.ativo
            FROM pessoa_juridica
            INNER JOIN unidade on unidade.id_pessoa_juridica = pessoa_juridica.id
            INNER JOIN pessoa on pessoa_juridica.id_pessoa = pessoa.id 
            INNER JOIN endereco on endereco.id = pessoa.id_endereco
            INNER JOIN cep on cep.id = endereco.cep  
        ';
		$binds = [ ];
		return $this->getDAOResponseFromPaginatedSelect( $binds, $pagination, $query_filter_collection, $query_order_collection, $sql,
			function (array $result_array) {
				return UnidadeMapper::getUnidadeDetailsVMListFromArray( $result_array );
			} );

	}

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

		$sql = <<<SQL
			SELECT
					pessoa.id as pessoa_id, pessoa.telefone_1 as telefone_1,
					pessoa.telefone_2 as telefone_2, pessoa.observacao as observacao,
					profissional_clinica.id_pessoa_juridica as pessoa_juridica_id,
					(select nome_fantasia from pessoa_juridica where id = pessoa_juridica_id) as nome_fantasia,
					(select razao_social from pessoa_juridica where id = pessoa_juridica_id) as razao_social,
					(select cnpj from pessoa_juridica where id = pessoa_juridica_id) as cnpj,
					endereco.id as endereco_id, endereco.numero as numero,
					endereco.complemento as complemento, endereco.referencias as referencias,
					cep.cep as cep, cep.id as cep_id, cep.bairro as bairro, 
					cep.logradouro as logradouro, cep.cidade as cidade, cep.estado as estado,
					(select descricao from unidade where id_pessoa_juridica = pessoa_juridica_id) as descricao,
					(select telemedicina from unidade where id_pessoa_juridica = pessoa_juridica_id) as telemedicina,
					(select id from unidade where id_pessoa_juridica = pessoa_juridica_id) as unidade_id
			FROM
				usuario, pessoa ,  pessoa_fisica , endereco, cep,
				profissional  Left join profissional_clinica  on profissional.id = profissional_clinica.id_profissional
			WHERE
				usuario.id = :id_usuario:
				AND usuario.id_pessoa = pessoa.id
				AND pessoa.id = profissional.id_pessoa
				AND pessoa.id = pessoa_fisica.id_pessoa
				AND pessoa.id_endereco = endereco.id
				AND endereco.cep = cep.id
		SQL;

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

	}

	public function getUnidade(QueryFilterCollection $query_filter_collection): DAOResponse {

		$sql = '
            SELECT 
            pj.id as pessoa_juridica_id
            ,pj.nome_fantasia as nome_fantasia
            ,pj.razao_social as razao_social 
            ,pj.cnpj as cnpj 
            ,p.id as pessoa_id
            ,p.telefone_1 as telefone_1
            ,p.telefone_2 as telefone_2
            ,p.observacao as observacao
            ,e.id as endereco_id
            ,e.cep as cep
            ,e.numero as numero
            ,e.complemento as complemento
            ,e.referencias as referencias
            ,c.id as cep_id 
            ,c.bairro as bairro
            ,c.logradouro as logradouro
            ,c.cidade as cidade
            ,c.estado as estado
            ,u.descricao as descricao
            ,u.telemedicina as telemedicina
            ,unidade.id as unidade_id
            FROM pessoa_juridica pj 
            INNER JOIN unidade u on u.id_pessoa_juridica = pj.id
            INNER JOIN pessoa p on pj.id_pessoa = p.id 
            INNER JOIN endereco e on e.id = p.id_endereco
            INNER JOIN cep c on e.cep = c.id 
        ';
		$binds = [ ];
		return $this->getDAOResponseFromUniqueRowSelect( $binds, $query_filter_collection, $sql,
			function (array $result_array) {
				return UnidadeMapper::getUnidadeDetailsVMFromArray( $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'], 'fk_unidade_id_pessoa_juridica' ) !== false) {
					$dao_response_errors ['pessoa_juridica'] = 'Essa pessoa juridica não existe.';
				}
			} else if ($error ['code'] === DAOResponseInterface::DUPLICATED_UNIQUE_KEY) {
				if (strpos( $error ['message'], '\'cnpj\'' ) !== false) {
					$dao_response_errors ['cnpj'] = 'Uma unidade com esse CNPJ já está cadastrada no sistema.';
				}
				if (strpos( $error ['message'], '\'pessoa.id_endereco\'' ) !== false) {
					$dao_response_errors ['cpf'] = 'Erro ao cadastrar pessoa.';
				}
			}
		}
		return $dao_response_errors;

	}

	public function persistUnidadeUpdateVM(int $id_unidade, int $id_pessoa_juridica, UnidadeUpdateViewModel $unidade_update_vm): DAOResponse {

		$dao_response = new DAOResponse();
		// $unidade_service_cf = new UnidadeServiceCF();
		$this->db->transStart();
		$status_persistence = $this->persistEnderecoFromUnidadeUpdateVM( $id_unidade, $unidade_update_vm );
		$status_persistence = $status_persistence && $this->persistPessoaFromUnidadeUpdateVM( $id_pessoa_juridica, $unidade_update_vm );
		$status_persistence = $status_persistence && $this->persistPessoaJuridicaFromUnidadeUpdateVM( $id_unidade, $id_pessoa_juridica, $unidade_update_vm );
		$status_persistence = $status_persistence && $this->persistUnidadeFromUnidadeUpdateVM( $id_unidade, $id_pessoa_juridica, $unidade_update_vm );
		$status_persistence = $status_persistence && $this->persistCepFromUnidadeUpdateVM( $id_pessoa_juridica, $unidade_update_vm );
		$error = $this->db->error();
		if ($error && $error ['code']) {
			$this->setDatabaseErrorsForUnidadeUpdate( $dao_response, $error );
			return $dao_response;
		} else if ($status_persistence) {
			// $unidade_edit_chamefacil = new UnidadeModel();
			// $response_unidade = $this->getIdCfUnidade($id_unidade);
			// $response_usuario = $unidade_service_cf->updateUnidadeCf($unidade_update_vm, $response_unidade[0]['id_chamefacil']);
			// if($response_usuario->Id > 0){
			$dao_response->setStatus( DAOResponseInterface::SUCESS );
			$this->db->transComplete();
			// }else{
			// $this->setDatabaseErrorsForUnidadeRegistration( $dao_response, $error );
			// }
		}
		$this->db->close();
		return $dao_response;

	}

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

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

	}

	private function persistCepFromUnidadeUpdateVM(int $id_pessoa_juridica, UnidadeUpdateViewModel &$unidade_update_vm): bool {

		$cep_model = new CEPModel();
		$cep = UnidadeMapper::getCepFromUnidadeUpdateVM( $unidade_update_vm );
		$sucess_update = $cep_model->updateCepByUnidadeID( $id_pessoa_juridica, $cep );
		return $sucess_update;

	}

	private function persistEnderecoFromUnidadeUpdateVM(int $id_unidade, UnidadeUpdateViewModel &$unidade_update_vm): bool {

		$endereco_model = new EnderecoModel();
		$endereco = UnidadeMapper::getEnderecoFromUnidadeUpdateVM( $unidade_update_vm );
		$sucess_update = $endereco_model->updateEnderecoByUnidadeID( $id_unidade, $endereco );
		return $sucess_update;

	}

	private function persistPessoaFromUnidadeUpdateVM(int $id_pessoa_juridica, UnidadeUpdateViewModel &$unidade_update_vm): bool {

		$pessoa_model = new PessoaModel();
		$pessoa = UnidadeMapper::getPessoaFromUnidadeUpdateVM( $unidade_update_vm );
		$sucess_update = $pessoa_model->updatePessoaByUnidadeID( $id_pessoa_juridica, $pessoa );
		return $sucess_update;

	}

	private function persistPessoaJuridicaFromUnidadeUpdateVM(int $id_unidade, int $id_pessoa_juridica, UnidadeUpdateViewModel &$unidade_update_vm): bool {

		$pessoa_juridica_model = new PessoaJuridicaModel();
		$pessoa_juridica = UnidadeMapper::getPessoaJuridicaFromUnidadeUpdateVM( $unidade_update_vm );
		$sucess_update = $pessoa_juridica_model->updatePessoaJuridicaByUnidadeID( $id_unidade, $id_pessoa_juridica, $pessoa_juridica );
		return $sucess_update;

	}

	private function persistUnidadeFromUnidadeUpdateVM(int $id_unidade, int $id_pessoa_juridica, UnidadeUpdateViewModel &$unidade_update_vm): bool {

		$pessoa_juridica_model = new UnidadeModel();
		$pessoa_juridica = UnidadeMapper::getUnidadeFromUnidadeUpdateVM( $unidade_update_vm );
		$sucess_update = $pessoa_juridica_model->updateUnidadeByPessoaJuridicaID( $id_pessoa_juridica, $pessoa_juridica );
		return $sucess_update;

	}

	// VALIDA SE UNIDADE EXISTE AO EDITAR
	public function getUnidadeFromId(int $id_unidade) {

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

	}

	public function getDadosUnidadeFromId(int $id_unidade) {

		$dao_response = new DAOResponse();
		$sql = <<<SQL
			select distinct
				ud.id,
				pj.id as pessoa_juridica_id, pj.nome_fantasia , pj.razao_social , pj.cnpj,
				p.telefone_1 as telefone, p.id_endereco,
				e.cep as cep_id, ce.cep , ce.bairro , ce.logradouro , ce.cidade , ce.estado,
				e.numero , e.complemento , e.referencias
			from
				unidade ud, pessoa_juridica pj, pessoa p, endereco e, cep ce
			where
				ud.id = :unidade_id:
				and ud.id_pessoa_juridica = pj.id
				and pj.id_pessoa = p.id
				and p.id_endereco = e.id
				and e.cep = ce.id
		SQL;
		$binds = [ 
			'unidade_id' => $id_unidade
		];
		$query = $this->db->query( $sql, $binds );
		$result_array = $query->getResultArray();
		if (count( $result_array ) > 0) {
			$dao_response->setStatus( DAOResponseInterface::SUCESS );
			$dao_response->setData( $result_array );
		} else {
			$dao_response->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
		}
		return ($dao_response);

	}

	public function getIdCfUnidade(int $id_unidade) {

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

	}

	public function getUnidadeToId(int $usuarioid): array {

		$sql = <<<SQL
			select 
					distinct un.id
			from 
				usuario u, profissional p , profissional_clinica pc , 
				pessoa_juridica pj, unidade un
			where
				u.id = :usuario_id:
				and u.id_pessoa = p.id_pessoa
				and pc.id_profissional = p.id
				and pc.id_pessoa_juridica = pj.id
				and pj.id = un.id_pessoa_juridica 
		SQL;

		$binds = [ 
			'usuario_id' => $usuarioid
		];

		$result_array = array ();
		$query = $this->db->query( $sql, $binds );
		$result_array = $query->getResultArray();

		return $result_array;

	}

	public function getUnidadesToUsuarioId(int $usuarioid): DAOResponse {

		$dao_response = new DAOResponse();

		try {

			$sql = <<<SQL
				select
						distinct un.id
				from
					usuario u, profissional p , profissional_clinica pc ,
					pessoa_juridica pj, unidade un
				where
					u.id = :usuario_id:
					and u.id_pessoa = p.id_pessoa
					and pc.id_profissional = p.id
					and pc.id_pessoa_juridica = pj.id
					and pj.id = un.id_pessoa_juridica
			SQL;

			$binds = [ 
				'usuario_id' => $usuarioid
			];

			$conn = db_connect();
			$query_result = $conn->query( $sql, $binds )
				->getResultArray();
			$errors = $conn->error();
			$conn->close();

			if (intval( $errors ['code'] ) != 0) {
				$dao_response->setErrors( $errors );
				$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
				$dao_response->setData( [ ] );
			} else {
				if (count( $query_result ) > 0) {
					$dao_response->setStatus( DAOResponseInterface::SUCESS );
					$dao_response->setData( $query_result );
				} else {
					$dao_response->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
					$dao_response->setData( [ ] );
				}
			}
		} catch ( Exception $e ) {
			$dao_response->setErrors( [ 
				'code' => $e->getCode(),
				'mensagem' => $e->getMessage()
			] );
			$dao_response->setStatus( DAOResponseInterface::UNKNOWN_ERROR );
			$dao_response->setData( [ ] );
		}
		return $dao_response;

	}

	public function persistUnidadeUF(UnidadeUFRegistrationViewModel $objregister): DAOResponse {

		$dao_response = new DAOResponse();

		$sql = <<<SQL
			insert into unidade_uf 
				(nome_unidade,id_unidade, id_uf, crc) values 
				(:unidade_nome:,:unidade_id:,:uf_id:,:cod_crc:) 
		SQL;

		$binds = [ 
			'unidade_nome' => $objregister->getNomeUnidade(),
			'unidade_id' => $objregister->getIdUnidade(),
			'uf_id' => $objregister->getIdUf(),
			'cod_crc' => $objregister->getCrc()
		];

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )->numRows;
		$errors = $conn->error();

		if (intval( $errors ['code'] ) != 0) {
			$dao_response->setErrors( $errors );
			$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$dao_response->setData( [ ] );
		} else {
			$newId = $conn->insertID();
			$dao_response->setStatus( DAOResponseInterface::SUCESS );
			$dao_response->setData( [ 
				'newId' => $newId
			] );
		}

		return $dao_response;

	}

	public function updateUnidadeUF(UnidadeUFUpdateViewModel $objregister): DAOResponse {

		$dao_response = new DAOResponse();

		$sql = <<<SQL
			update unidade_uf
				set nome_unidade = :unidade_nome:,
					id_unidade = :unidade_id:, 
					id_uf = :uf_id:,
					crc = :cod_crc:
			where
				id = :id:
		SQL;

		$binds = [ 
			'id' => $objregister->getId(),
			'unidade_nome' => $objregister->getNomeUnidade(),
			'unidade_id' => $objregister->getIdUnidade(),
			'uf_id' => $objregister->getIdUf(),
			'cod_crc' => $objregister->getCrc()
		];

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )->numRows;
		$errors = $conn->error();

		if (intval( $errors ['code'] ) != 0) {
			$dao_response->setErrors( $errors );
			$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$dao_response->setData( [ ] );
		} else {
			$affect = $conn->affectedRows();
			if ($affect == 1) {
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
			} else {
				$dao_response->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
			}
			$dao_response->setData( [ ] );
		}

		return $dao_response;

	}

	public function getListUnidadeFisicasAllUF(): DAOResponse {

		$dao_response = new DAOResponse();

		$sql = <<<SQL
			select 
				unf.id, unf.id_unidade, unf.id_uf, unf.crc, unf.nome_unidade
			from 
				unidade_uf  unf , unidade un
			where
				unf.id_unidade = un.id
				and un.telemedicina = 0
		SQL;

		$binds = [ ];

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )
			->getResultArray();
		$errors = $conn->error();

		if (intval( $errors ['code'] ) != 0) {
			$dao_response->setErrors( $errors );
			$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$dao_response->setData( [ ] );
		} else {
			if (count( $result ) > 0) {
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
				$dao_response->setData( $result );
			} else {
				$dao_response->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
				$dao_response->setData( [ ] );
			}
		}

		return $dao_response;

	}

	public function getListUfWithUnidadesFisicas(): DAOResponse {

		$dao_response = new DAOResponse();

		$sql = <<<SQL
			select 
				distinct uf.id , uf.descricao as estado, uf.sigla
			from 
				unidade_uf  unf , unidade un , uf
			where
				unf.id_unidade = un.id
				and un.telemedicina = 0
				and unf.id_uf = uf.id 
		SQL;

		$binds = [ ];

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )
			->getResultArray();
		$errors = $conn->error();

		if (intval( $errors ['code'] ) != 0) {
			$dao_response->setErrors( $errors );
			$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$dao_response->setData( [ ] );
		} else {
			if (count( $result ) > 0) {
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
				$dao_response->setData( $result );
			} else {
				$dao_response->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
				$dao_response->setData( [ ] );
			}
		}

		return $dao_response;

	}

	public function getListUnidadeFisicaByUF(int $uf): DAOResponse {

		$dao_response = new DAOResponse();

		$sql = <<<SQL
			select
				unf.id, unf.id_unidade, unf.id_uf, uf.descricao as estado,
				uf.sigla,unf.crc, unf.nome_unidade
			from
				unidade_uf  unf , unidade un, uf
			where
				unf.id_uf = :id_uf:
				and unf.id_unidade = un.id
				and un.telemedicina = 0
				and un.id_status = 1
				and unf.id_uf = uf.id
				
		SQL;

		$binds = [ 
			'id_uf' => $uf
		];

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )
			->getResultArray();
		$errors = $conn->error();

		if (intval( $errors ['code'] ) != 0) {
			$dao_response->setErrors( $errors );
			$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$dao_response->setData( [ ] );
		} else {
			if (count( $result ) > 0) {
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
				$dao_response->setData( $result );
			} else {
				$dao_response->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
				$dao_response->setData( [ ] );
			}
		}

		return $dao_response;

	}

	public function getListUF(): DAOResponse {

		$dao_response = new DAOResponse();

		$sql = <<<SQL
			select
				distinct uf.id , uf.descricao as estado, uf.sigla
			from
				uf
		SQL;

		$binds = [ ];

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )
			->getResultArray();
		$errors = $conn->error();

		if (intval( $errors ['code'] ) != 0) {
			$dao_response->setErrors( $errors );
			$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$dao_response->setData( [ ] );
		} else {
			if (count( $result ) > 0) {
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
				$dao_response->setData( $result );
			} else {
				$dao_response->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
				$dao_response->setData( [ ] );
			}
		}

		return $dao_response;

	}

	public function getListUnidadesAllUF(Pagination $pagination): DAOResponse {

		$dao_response = new DAOResponse();

		$page = $pagination->getCurrentPage();
		$itens_per_page = $pagination->getPerPage();
		$offset = ($page - 1) * $itens_per_page;

		$sql_num = <<<SQL
			select
				count(*) total
			from
				unidade_uf  unf , unidade un, uf
			where
				unf.id_unidade = un.id
				and un.id_status = 1
				and unf.id_uf = uf.id
			
		SQL;

		$conn_num = db_connect();
		$result = $conn_num->query( $sql_num, [ ] )
			->getResultArray();
		$pagination->setNumRows( $result [0] ['total'] );

		$sql = <<<SQL
			select
				unf.id, unf.id_unidade, unf.id_uf, uf.descricao as estado,
				uf.sigla,unf.crc, unf.nome_unidade
			from
				unidade_uf  unf , unidade un, uf
			where
				unf.id_unidade = un.id				
				and un.id_status = 1
				and unf.id_uf = uf.id
			limit :offset: , :num_itens:
		SQL;

		$binds = [ 
			'offset' => $offset,
			'num_itens' => $itens_per_page
		];

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )
			->getResultArray();
		$errors = $conn->error();

		if (intval( $errors ['code'] ) != 0) {
			$dao_response->setErrors( $errors );
			$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$dao_response->setData( [ ] );
		} else {
			if (count( $result ) > 0) {
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
				$dao_response->setData( 
					[ 
						'dados' => $result,
						'paginacao' => [ 
							'current_page' => $pagination->getCurrentPage(),
							'num_rows' => $pagination->getNumRows(),
							'first_page' => $pagination->calculateFirstPage(),
							'last_page' => $pagination->calculateLastPage(),
							'previous_page' => $pagination->calculatePreviousPage(),
							'next_page' => $pagination->calculateNextPage(),
							'per_page' => $pagination->getPerPage()
						]
					] );
			} else {
				$dao_response->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
				$dao_response->setData( [ ] );
			}
		}

		return $dao_response;

	}

	public function changeStatusByUnidadeId(int $id_unidade, int $status) {

		$dao_response = new DAOResponse();

		$sql = <<<SQL
			update unidade
				set ativo = :ativo:
			where
				id = :id_unidade:
		SQL;

		$binds = [ 
			'id_unidade' => $id_unidade,
			'ativo' => $status
		];

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )->numRows;
		$errors = $conn->error();

		if (intval( $errors ['code'] ) != 0) {
			$dao_response->setErrors( $errors );
			$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$dao_response->setData( [ ] );
		} else {
			$affect = $conn->affectedRows();
			if ($affect == 1) {
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
			} else {
				$dao_response->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
			}
			$dao_response->setData( [ ] );
		}

		return $dao_response;

	}

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

		$sql = '
            SELECT
            pessoa_juridica.id as pessoa_juridica_id
            ,pessoa_juridica.nome_fantasia as nome_fantasia
            ,pessoa_juridica.razao_social as razao_social
            ,pessoa_juridica.cnpj as cnpj
            ,pessoa.id as pessoa_id
            ,pessoa.telefone_1 as telefone_1
            ,pessoa.telefone_2 as telefone_2
            ,pessoa.observacao as observacao
            ,endereco.id as endereco_id
            ,cep.cep as cep
            ,endereco.numero as numero
            ,endereco.complemento as complemento
            ,endereco.referencias as referencias
            ,cep.id as cep_id
            ,cep.bairro as bairro
            ,cep.logradouro as logradouro
            ,cep.cidade as cidade
            ,cep.estado as estado
            ,unidade.descricao
            ,unidade.telemedicina
            ,unidade.id as unidade_id
			,unidade.ativo as ativo
            FROM pessoa_juridica
            INNER JOIN unidade on unidade.id_pessoa_juridica = pessoa_juridica.id
            INNER JOIN pessoa on pessoa_juridica.id_pessoa = pessoa.id
            INNER JOIN endereco on endereco.id = pessoa.id_endereco
            INNER JOIN cep on cep.id = endereco.cep
			WHERE unidade.ativo = 1
        ';
		$binds = [ ];
		return $this->getDAOResponseFromPaginatedSelect( $binds, $pagination, $query_filter_collection, $query_order_collection, $sql,
			function (array $result_array) {
				return UnidadeMapper::getUnidadeDetailsVMListFromArray( $result_array );
			} );

	}

}
