<?php

namespace App\DAO;

use App\DAO\DAOResponse\DAOResponse;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\DAO\Pagination\Pagination;
use App\Entities\ClassificacaoRisco\ClassificacaoRisco;
use App\Mappers\ClassificacaoRiscoMapper;
use App\Models\ClassificacaoRiscoModel;
use App\Utils\Collections\QueryFilterCollection;
use App\Utils\Collections\QueryOrderCollection;
use App\ViewModels\ClassificacaoRisco\ClassificacaoRiscoRegistrationViewModel\ClassificacaoRiscoRegistrationViewModel;
use App\ViewModels\ClassificacaoRisco\ClassificacaoRiscoUpdateViewModel\ClassificacaoRiscoUpdateViewModel;
use Exception;

class ClassificacaoRiscoDAO extends DAO {

	public function persistClassificacaoRiscoRegistrationVM(ClassificacaoRiscoRegistrationViewModel $classificacao_risco_registration_vm): DAOResponse {

		$dao_response = new DAOResponse();
		try {
			$this->db->transStart();
			$classificacao_risco = $this->persistClassificacaoRiscoFromClassificacaoRiscoRegistrationVM( $classificacao_risco_registration_vm );
			$error = $this->db->error();
			if ($error && $error ['code']) {
				$this->setDatabaseErrorsForClassificacaoRiscoRegistration( $dao_response, $error );
			} else {
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
				$dao_response->setData( $classificacao_risco );
				$this->db->transComplete();
			}
		} catch ( Exception $exception ) {
			$this->setDatabaseErrorsForClassificacaoRiscoRegistration( $dao_response, $this->db->error() );
		}

		return $dao_response;

	}

	private function setDatabaseErrorsForClassificacaoRiscoRegistration(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 persistClassificacaoRiscoFromClassificacaoRiscoRegistrationVM(
			ClassificacaoRiscoRegistrationViewModel &$classificacao_risco_registration_vm): ClassificacaoRisco {

		$classificacao_risco_model = new ClassificacaoRiscoModel();
		$classificacao_risco = ClassificacaoRiscoMapper::getClassificacaoRiscoFromClassificacaoRiscoRegistrationVM( $classificacao_risco_registration_vm );
		$classificacao_risco_model->registerClassificacaoRisco( $classificacao_risco );
		if (!$classificacao_risco->getId()) {
			throw new Exception( 'O cadastro de paciente não foi teve êxito' );
		}
		return $classificacao_risco;

	}

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

		$sql = '
            SELECT 
            classificacao_risco.id as id,
            classificacao_risco.descricao as descricao,
            classificacao_risco.id_unidade as id_unidade,
            classificacao_risco.cor as cor,
            classificacao_risco.valor as valor,
            classificacao_risco.criado_em as criado_em,
            classificacao_risco.atualizado_em as atualizado_em,
            classificacao_risco.desativado_em as desativado_em,
            classificacao_risco.criado_por as criado_por,
            classificacao_risco.alterado_por as alterado_por,
            classificacao_risco.desativado_por as desativado_por,
            unidade.descricao as nome_unidade
            FROM classificacao_risco inner join unidade on unidade.id = classificacao_risco.id_unidade
        ';
		$binds = [ ];
		return $this->getDAOResponseFromPaginatedSelect( $binds, $pagination, $query_filter_collection, $query_order_collection, $sql,
			function (array $result_array) {
				return ClassificacaoRiscoMapper::getClassificacaoRiscoDetailsVMListFromArray( $result_array );
			} );

	}

	public function getClassificacaoRisco(QueryFilterCollection $query_filter_collection): DAOResponse {

		$sql = '
            SELECT 
            classificacao_risco.id as id,
            classificacao_risco.descricao as descricao,
            classificacao_risco.id_unidade as id_unidade,
            classificacao_risco.cor as cor,
            classificacao_risco.valor as valor,
            classificacao_risco.criado_em as criado_em,
            classificacao_risco.atualizado_em as atualizado_em,
            classificacao_risco.desativado_em as desativado_em,
            classificacao_risco.criado_por as criado_por,
            classificacao_risco.alterado_por as alterado_por,
            classificacao_risco.desativado_por as desativado_por,
            unidade.descricao as nome_unidade
            FROM classificacao_risco inner join unidade on unidade.id = classificacao_risco.id_unidade
            
        ';
		$binds = [ ];
		return $this->getDAOResponseFromUniqueRowSelect( $binds, $query_filter_collection, $sql,
			function (array $result_array) {
				$classificacao_riscoVM = ClassificacaoRiscoMapper::getClassificacaoRiscoDetailsVMFromArray( $result_array [0] );
				return $classificacao_riscoVM;
			} );

	}

	public function getClassificacaoRiscoFromId(int $id_classificacao_risco) {

		$sql = "  SELECT * FROM classificacao_risco WHERE id=? ";

		$binds = [ 
			$id_classificacao_risco
		];
		$query = $this->db->query( $sql, $binds );
		$result_array = $query->getResultArray();

		return ($result_array);

	}

	public function persistClassificacaoRiscoUpdateVM(int $id_paciente, ClassificacaoRiscoUpdateViewModel $classificacao_risco_update_vm): DAOResponse {

		$dao_response = new DAOResponse();
		$this->db->transStart();
		$status_persistence = $this->persistClassificacaoRiscoFromClassificacaoRiscoUpdateVM( $id_paciente, $classificacao_risco_update_vm );
		$error = $this->db->error();
		if ($error && $error ['code']) {
			$this->setDatabaseErrorsForClassificacaoRiscoUpdate( $dao_response, $error );
			return $dao_response;
		} else if ($status_persistence) {
			$this->db->transComplete();
			$dao_response->setStatus( DAOResponseInterface::SUCESS );
		}
		$this->db->close();
		return $dao_response;

	}

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

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

	}

	private function persistClassificacaoRiscoFromClassificacaoRiscoUpdateVM(int $id_paciente, ClassificacaoRiscoUpdateViewModel &$classificacao_risco_update_vm): bool {

		$classificacao_risco_model = new ClassificacaoRiscoModel();
		$classificacao_risco = ClassificacaoRiscoMapper::getClassificacaoRiscoFromClassificacaoRiscoUpdateVM( $classificacao_risco_update_vm );
		$sucess_update = $classificacao_risco_model->updateClassificacaoRiscoByID( $id_paciente, $classificacao_risco );
		return $sucess_update;

	}

	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_classificacao_risco_id_unidade' ) !== false) {
					$dao_response_errors ['unidade'] = 'Essa unidade não existe.';
				}
			} else if ($error ['code'] === DAOResponseInterface::DUPLICATED_UNIQUE_KEY) {
				if (strpos( $error ['message'], '\'cpf\'' ) !== false) {
					$dao_response_errors ['cpf'] = 'Uma pessoa com esse CPF já está cadastrada no sistema.';
				}
				if (strpos( $error ['message'], '\'pessoa_fisica.rg\'' ) !== false) {
					$dao_response_errors ['rg'] = 'Uma pessoa com esse RG já está cadastrada no sistema.';
				}
				if (strpos( $error ['message'], '\'email\'' ) !== false) {
					$dao_response_errors ['email'] = 'Uma pessoa com esse email já está cadastrada no sistema.';
				}
			}
		}
		return $dao_response_errors;

	}

	public function persistClassificacaoRiscoDeleteVM(int $id_paciente): DAOResponse {

		$dao_response = new DAOResponse();
		$this->db->transStart();
		$status_persistence = $this->deleteClassificacaoRisco( $id_paciente );
		$error = $this->db->error();
		if ($error && $error ['code']) {
			$this->setDatabaseErrorsForClassificacaoRiscoUpdate( $dao_response, $error );
			return $dao_response;
		} else if ($status_persistence) {
			$this->db->transComplete();
			$dao_response->setStatus( DAOResponseInterface::SUCESS );
		}
		$this->db->close();
		return $dao_response;

	}

	public function deleteClassificacaoRisco(int $id_classificacao_risco): bool {

		$classificacao_risco_model = new ClassificacaoRiscoModel();
		$sucess_update = $classificacao_risco_model->deleteClassificacaoRiscoByID( $id_classificacao_risco );
		return $sucess_update;

	}

}
