<?php

namespace App\DAO;

use App\DAO\DAOResponse\DAOResponse;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\DAO\Pagination\Pagination;
use App\Entities\TipoProcedimento\TipoProcedimento;
use App\Mappers\TipoProcedimentoMapper;
use App\Models\TipoProcedimentoModel;
use App\Services\LogService;
use App\Utils\Collections\QueryFilterCollection;
use App\Utils\Collections\QueryOrderCollection;
use App\ViewModels\TipoProcedimento\TipoProcedimentoRegistrationViewModel\TipoProcedimentoRegistrationViewModel;
use App\ViewModels\TipoProcedimento\TipoProcedimentoUpdateViewModel\TipoProcedimentoUpdateViewModel;
use Exception;

class TipoProcedimentoDAO extends DAO {

	public function persistTipoProcedimentoRegistrationVM(TipoProcedimentoRegistrationViewModel $tipo_procedimento_registration_vm): DAOResponse {

		try {
			$tipo_procedimento = $this->persistTipoProcedimento( $tipo_procedimento_registration_vm );
			$error = $this->db->error();
			if ($error && $error ['code']) {
				$status_persistence = $error ['code'];
			} else {
				$status_persistence = !!$tipo_procedimento->getId() ? DAOResponseInterface::SUCESS : DAOResponseInterface::DATABASE_CONNECTION_ERROR;
			}
		} catch ( Exception $exception ) {
			log_message( 'error', json_encode( $this->db->error() ) );
			$status_persistence = DAOResponseInterface::DATABASE_CONNECTION_ERROR;
			$tipo_procedimento = null;
		}
		$this->db->close();
		$dao_response = DAOResponse::builder()->setStatus( $status_persistence )
			->build();
		if ($status_persistence === DAOResponseInterface::SUCESS) {
			$dao_response->setData( $tipo_procedimento );
		}
		return $dao_response;

	}

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

		$sql = '
            SELECT 
                id,
                descricao 
            FROM tipo_procedimento
        ';
		return $this->getDAOResponseFromPaginatedSelect( [ ], $pagination, $query_filter_collection, $query_order_collection, $sql,
			function (array $result_array) {
				return TipoProcedimentoMapper::getTipoProcedimentoDetailsVMCollectionFromArray( $result_array );
			} );

	}

	public function deleteTipoProcedimento(int $id_procedimento): DAOResponse {

		$tipo_procedimento_model = new TipoProcedimentoModel();
		$dao_response = $this->getDAOResponseForDeletion( $tipo_procedimento_model, $id_procedimento );
		return $dao_response;

	}

	private function persistTipoProcedimento(TipoProcedimentoRegistrationViewModel $tipo_procedimento_registration_vm): TipoProcedimento {

		$tipo_procedimento_model = new TipoProcedimentoModel();
		$tipo_procedimento = TipoProcedimentoMapper::getTipoProcedimentoFromTipoProcedimentoRegistrationViewModel( $tipo_procedimento_registration_vm );
		$tipo_procedimento_model->registerTipoProcedimento( $tipo_procedimento );
		return $tipo_procedimento;

	}

	public function getTipoProcedimento(QueryFilterCollection $query_filter_collection): DAOResponse {

		$sql = '
            SELECT
                tipo_procedimento.id AS id,
                tipo_procedimento.descricao AS descricao
            FROM
                tipo_procedimento
        ';
		$binds = [ ];
		return $this->getDAOResponseFromUniqueRowSelect( $binds, $query_filter_collection, $sql,
			function (array $result_array) {
				return TipoProcedimentoMapper::getTipoProcedimentoDetailsVMFromArray( $result_array [0] );
			} );

	}

	public function persistTipoProcedimentoUpdateVM(int $id_procedimento, TipoProcedimentoUpdateViewModel $especie_update_vm): DAOResponse {

		$status_persistence = $this->persistTipoProcedimentoFromTipoProcedimentoUpdateVM( $id_procedimento, $especie_update_vm );
		$error = $this->db->error();
		$this->db->close();
		$dao_response = new DAOResponse();
		if ($error && $error ['code']) {
			$status_response = $error ['code'];
			$dao_response_errors = [ ];
			$dao_response->setErrors( $dao_response_errors );
			(new LogService())->log_error( $status_response, "Ocorreu um erro durante a atualização do procedimento $id_procedimento",
				$especie_update_vm->toArray() );
		} else {
			$status_response = $status_persistence ? DAOResponseInterface::SUCESS : DAOResponseInterface::RECORD_NOT_FOUND;
		}
		$dao_response->setStatus( $status_response );
		return $dao_response;

	}

	private function persistTipoProcedimentoFromTipoProcedimentoUpdateVM(int $id_procedimento, TipoProcedimentoUpdateViewModel $especie_update_vm): bool {

		$especie_model = new TipoProcedimentoModel();
		$especie = TipoProcedimentoMapper::getTipoProcedimentoFromTipoProcedimentoUpdateVM( $especie_update_vm );
		$sucess_update = $especie_model->updateTipoProcedimentoByID( $id_procedimento, $especie );
		return $sucess_update;

	}

	public function getTipoProcedimentoByProcedimentoId(int $procedimentoId): DAOResponse {

		$sql = <<<SQL
			select p.id , p.descricao as procedimento , tp.id as tipo_id, tp.descricao as tipo_procedimento
			from procedimento p, tipo_procedimento tp
			where p.id = :procedimento_id: and p.id_tipo_procedimento = tp.id 
		SQL;

		$binds = [ 
			'procedimento_id' => $procedimentoId
		];
		$dao_response = new DAOResponse();
		$conn = db_connect();
		$result = $conn->query( $sql, $binds )
			->getResultArray();
		$errors = $conn->error();

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

		return $dao_response;

	}

	public function getTipoProcedimentoByRequisicaoId(int $requisicaoId): DAOResponse {

		$sql = <<<SQL
			select 
				rp.id as requisicao_id, cp.id as convenio_procedimento_id, 
				cp.id_procedimento , p.id_tipo_procedimento , tp.descricao
			from 
				requisicao_procedimento rp, convenio_procedimento cp , 
				procedimento p , tipo_procedimento tp
			where
				rp.id =:id_requisicao:
				and rp.id_convenio_procedimento = cp.id
				and cp.id_procedimento = p.id
				and p.id_tipo_procedimento = tp.id 
		
		SQL;
		
		$binds = [
				'id_requisicao' => $requisicaoId
		];
		$dao_response = new DAOResponse();
		$conn = db_connect();
		$result = $conn->query( $sql, $binds )
		->getResultArray();
		$errors = $conn->error();
		
		if ($errors ['code'] != 0) {
			$dao_response->setErrors( $errors );
			$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
		} else {
			if(count($result) == 0) {
				$dao_response->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );				
			} else {
				$dao_response->setStatus( DAOResponseInterface::SUCESS );
				$dao_response->setData( $result );
			}
			
		}
		
		return $dao_response;

	}

}