<?php

namespace App\Controllers;

use App\DAO\Filter\QueryFilter;
use App\DAO\Filter\QueryFilterTranslator;
use App\DAO\Order\QueryOrderTranslator;
use App\Services\ProcedimentoService;
use App\Services\ServiceResponse\ServiceResponseInterface;
use App\Utils\Collections\QueryFilterCollection;
use App\Utils\Collections\QueryOrderCollection;
use App\Validations\ProcedimentoValidation;
use CodeIgniter\HTTP\Response;
use CodeIgniter\HTTP\ResponseInterface;

class ProcedimentoController extends BaseController {

	public function registerProcedimento(): Response {

		if (!$this->validate( ProcedimentoValidation::register() )) {
			return $this->response->setJSON( [ 
				'message' => 'Informe os dados corretamente.',
				'errors' => $this->validation->getErrors()
			] );
		}

		$procedimento_service_response = (new ProcedimentoService())->registerProcedimento( $_POST );
		$response_messages = [ 
			ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro de conexão com o banco de dados.'
			],
			ServiceResponseInterface::SUCESS => [ 
				'code' => ResponseInterface::HTTP_OK,
				'message' => 'O procedimento foi cadastrado com sucesso.'
			],
			ServiceResponseInterface::VALIDATION_PARAMS_ERROR => [ 
				'code' => ResponseInterface::HTTP_BAD_REQUEST,
				'message' => 'Informe os dados corretamente.'
			],
			ServiceResponseInterface::SERVICE_INTERNAL_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			]
		];
		return $this->getResponse( $procedimento_service_response, $response_messages );

	}

	public function getProcedimentoList(): Response {

		$pagination = $this->getPaginationFromRequest();

		if ($_GET ['sort'] === null) {
			$_GET ['sort'] = "descricao";
		}

		$query_filter_collection = new QueryFilterCollection( $_GET, QueryFilterTranslator::procedimento() );
		$query_order_collection = new QueryOrderCollection( $_GET, QueryOrderTranslator::procedimento() );
		$procedimento_service_response = (new ProcedimentoService())->getProcedimentoList( $pagination, $query_filter_collection, $query_order_collection );
		$response_messages = [ 
			ServiceResponseInterface::SUCESS => [ 
				'code' => ResponseInterface::HTTP_OK,
				'message' => 'Os dados dos procedimentos foram encontrados com sucesso.'
			],
			ServiceResponseInterface::RECORD_NOT_FOUND => [ 
				'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
				'message' => 'Nenhum registro foi encontrado.'
			],
			ServiceResponseInterface::SERVICE_INTERNAL_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			],
			ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			]
		];
		return $this->getResponse( $procedimento_service_response, $response_messages );

	}

	public function getProcedimentoConsultaList(int $unidade_id): Response {

		$pagination = $this->getPaginationFromRequest();

		if ($_GET ['sort'] === null) {
			$_GET ['sort'] = "descricao";
		}

		$query_filter_collection = new QueryFilterCollection( $_GET, QueryFilterTranslator::procedimento() );
		$query_order_collection = new QueryOrderCollection( $_GET, QueryOrderTranslator::procedimento() );
		$procedimento_service_response = (new ProcedimentoService())->getProcedimentoConsultaList( $pagination, $query_filter_collection,
			$query_order_collection, $unidade_id );
		$response_messages = [ 
			ServiceResponseInterface::SUCESS => [ 
				'code' => ResponseInterface::HTTP_OK,
				'message' => 'Os dados dos procedimentos foram encontrados com sucesso.'
			],
			ServiceResponseInterface::RECORD_NOT_FOUND => [ 
				'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
				'message' => 'Nenhum registro foi encontrado.'
			],
			ServiceResponseInterface::SERVICE_INTERNAL_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			],
			ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			]
		];
		return $this->getResponse( $procedimento_service_response, $response_messages );

	}

	public function getProcedimentoExameList(int $unidade_id): Response {

		$pagination = $this->getPaginationFromRequest();

		if ($_GET ['sort'] === null) {
			$_GET ['sort'] = "descricao";
		}

		$query_filter_collection = new QueryFilterCollection( $_GET, QueryFilterTranslator::procedimento() );
		$query_order_collection = new QueryOrderCollection( $_GET, QueryOrderTranslator::procedimento() );
		$procedimento_service_response = (new ProcedimentoService())->getProcedimentoExameList( $pagination, $query_filter_collection, $query_order_collection,
			$unidade_id );
		$response_messages = [ 
			ServiceResponseInterface::SUCESS => [ 
				'code' => ResponseInterface::HTTP_OK,
				'message' => 'Os dados dos procedimentos foram encontrados com sucesso.'
			],
			ServiceResponseInterface::RECORD_NOT_FOUND => [ 
				'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
				'message' => 'Nenhum registro foi encontrado.'
			],
			ServiceResponseInterface::SERVICE_INTERNAL_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			],
			ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			]
		];
		return $this->getResponse( $procedimento_service_response, $response_messages );

	}
	
	public function getProcedimentoHigieneList(int $unidade_id): Response {
	    
	    $pagination = $this->getPaginationFromRequest();
	    
	    if ($_GET ['sort'] === null) {
	        $_GET ['sort'] = "descricao";
	    }
	    
	    $query_filter_collection = new QueryFilterCollection( $_GET, QueryFilterTranslator::procedimento() );
	    $query_order_collection = new QueryOrderCollection( $_GET, QueryOrderTranslator::procedimento() );
	    $procedimento_service_response = (new ProcedimentoService())->getProcedimentoHigieneList( $pagination, $query_filter_collection, $query_order_collection,
	        $unidade_id );
	    $response_messages = [
	        ServiceResponseInterface::SUCESS => [
	            'code' => ResponseInterface::HTTP_OK,
	            'message' => 'Os dados dos procedimentos foram encontrados com sucesso.'
	        ],
	        ServiceResponseInterface::RECORD_NOT_FOUND => [
	            'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
	            'message' => 'Nenhum registro foi encontrado.'
	        ],
	        ServiceResponseInterface::SERVICE_INTERNAL_ERROR => [
	            'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
	            'message' => 'Erro interno do servidor.'
	        ],
	        ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [
	            'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
	            'message' => 'Erro interno do servidor.'
	        ]
	    ];
	    return $this->getResponse( $procedimento_service_response, $response_messages );
	    
	}

	public function getProcedimentoInternacaoList(int $unidade_id): Response {

		$pagination = $this->getPaginationFromRequest();

		if ($_GET ['sort'] === null) {
			$_GET ['sort'] = "descricao";
		}

		$query_filter_collection = new QueryFilterCollection( $_GET, QueryFilterTranslator::procedimento() );
		$query_order_collection = new QueryOrderCollection( $_GET, QueryOrderTranslator::procedimento() );
		$procedimento_service_response = (new ProcedimentoService())->getProcedimentoInternacaoList( $pagination, $query_filter_collection,
			$query_order_collection, $unidade_id );
		$response_messages = [ 
			ServiceResponseInterface::SUCESS => [ 
				'code' => ResponseInterface::HTTP_OK,
				'message' => 'Os dados dos procedimentos foram encontrados com sucesso.'
			],
			ServiceResponseInterface::RECORD_NOT_FOUND => [ 
				'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
				'message' => 'Nenhum registro foi encontrado.'
			],
			ServiceResponseInterface::SERVICE_INTERNAL_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			],
			ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			]
		];
		return $this->getResponse( $procedimento_service_response, $response_messages );

	}

	public function getProcedimentoMedicacaoList(int $unidade_id): Response {

		$pagination = $this->getPaginationFromRequest();

		if ($_GET ['sort'] === null) {
			$_GET ['sort'] = "descricao";
		}

		$query_filter_collection = new QueryFilterCollection( $_GET, QueryFilterTranslator::procedimento() );
		$query_order_collection = new QueryOrderCollection( $_GET, QueryOrderTranslator::procedimento() );
		$procedimento_service_response = (new ProcedimentoService())->getProcedimentoMedicacaoList( $pagination, $query_filter_collection,
			$query_order_collection, $unidade_id );
		$response_messages = [ 
			ServiceResponseInterface::SUCESS => [ 
				'code' => ResponseInterface::HTTP_OK,
				'message' => 'Os dados dos procedimentos foram encontrados com sucesso.'
			],
			ServiceResponseInterface::RECORD_NOT_FOUND => [ 
				'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
				'message' => 'Nenhum registro foi encontrado.'
			],
			ServiceResponseInterface::SERVICE_INTERNAL_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			],
			ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			]
		];
		return $this->getResponse( $procedimento_service_response, $response_messages );

	}

	public function getProcedimentoCirurgiaList(int $unidade_id): Response {

		$pagination = $this->getPaginationFromRequest();

		if ($_GET ['sort'] === null) {
			$_GET ['sort'] = "descricao";
		}

		$query_filter_collection = new QueryFilterCollection( $_GET, QueryFilterTranslator::procedimento() );
		$query_order_collection = new QueryOrderCollection( $_GET, QueryOrderTranslator::procedimento() );
		$procedimento_service_response = (new ProcedimentoService())->getProcedimentoCirurgiaList( $pagination, $query_filter_collection,
			$query_order_collection, $unidade_id );
		$response_messages = [ 
			ServiceResponseInterface::SUCESS => [ 
				'code' => ResponseInterface::HTTP_OK,
				'message' => 'Os dados dos procedimentos foram encontrados com sucesso.'
			],
			ServiceResponseInterface::RECORD_NOT_FOUND => [ 
				'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
				'message' => 'Nenhum registro foi encontrado.'
			],
			ServiceResponseInterface::SERVICE_INTERNAL_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			],
			ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			]
		];
		return $this->getResponse( $procedimento_service_response, $response_messages );

	}

	public function searchProcedimentoByID(int $id_procedimento): Response {

		$query_filter = QueryFilter::builder()->setTable( 'procedimento' )
			->setNameParam( 'id' )
			->setValue( $id_procedimento )
			->setIsExact( true )
			->build();
		$procedimento_service_response = (new ProcedimentoService())->getProcedimento( $query_filter );
		$response_messages = [ 
			ServiceResponseInterface::SUCESS => [ 
				'code' => ResponseInterface::HTTP_OK,
				'message' => 'Os dados do procedimento foram encontrados com sucesso.'
			],
			ServiceResponseInterface::RECORD_NOT_FOUND => [ 
				'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
				'message' => 'Nenhum registro foi encontrado.'
			],
			ServiceResponseInterface::SERVICE_INTERNAL_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			],
			ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			]
		];
		return $this->getResponse( $procedimento_service_response, $response_messages );

	}

	public function deleteProcedimento(int $id_procedimento) {

		$procedimento_service_response = (new ProcedimentoService())->deleteProcedimento( $id_procedimento );
		$response_messages = [ 
			ServiceResponseInterface::SUCESS => [ 
				'code' => ResponseInterface::HTTP_OK,
				'message' => 'A exclusão foi efetuda com sucesso.'
			],
			ServiceResponseInterface::RECORD_NOT_FOUND => [ 
				'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
				'message' => 'Nenhum registro foi encontrado.'
			],
			ServiceResponseInterface::RECORD_IS_LINKED => [ 
				'code' => ResponseInterface::HTTP_BAD_REQUEST,
				'message' => 'Esse de procedimento está vinculado a outros cadastros do sistema. Portanto, não pode ser excluído.'
			],
			ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro interno do servidor.'
			]
		];
		return $this->getResponse( $procedimento_service_response, $response_messages );

	}

	public function updateProcedimento(int $id_procedimento): Response {

		if (!$this->validate( ProcedimentoValidation::update() )) {
			return $this->response->setJSON( [ 
				'message' => 'Informe os dados corretamente.',
				'errors' => $this->validation->getErrors()
			] );
		}
		$procedimento_service_response = (new ProcedimentoService())->updateProcedimentoData( $id_procedimento, $_POST );
		$response_messages = [ 
			ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [ 
				'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
				'message' => 'Erro de conexão com o banco de dados.'
			],
			ServiceResponseInterface::RECORD_NOT_FOUND => [ 
				'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
				'message' => 'O procedimento não foi encontrado.'
			],
			ServiceResponseInterface::SUCESS => [ 
				'code' => ResponseInterface::HTTP_OK,
				'message' => 'Os dados do procedimento foram atualizados com sucesso.'
			],
			ServiceResponseInterface::VALIDATION_PARAMS_ERROR => [ 
				'code' => ResponseInterface::HTTP_BAD_REQUEST,
				'message' => 'Informe os dados corretamente.'
			]
		];
		return $this->getResponse( $procedimento_service_response, $response_messages );

	}

	public function getProcedimentoByUnidade(int $unidadeId) {

		$sql = <<<SQL
			select
				p.id as procedimento_id, p.descricao as procedimento_descricao,
				p.id_tipo_procedimento as tipo_procedimento_id ,tp.descricao as tipo_procedimento_descricao,
				cp.id_unidade as unidade_id, cp.id as convenio_procedimento_id , cp.id_convenio as convenio_id ,
				tc.id tipo_convenio_id, tc.descricao as tipo_convenio_descricao
			from 
				procedimento p , convenio_procedimento cp , tipo_procedimento tp , convenio c , tipo_convenio tc
			where
				cp.id_unidade = :unidade_id:
				and cp.id_procedimento = p.id
				and cp.desativado_por is not null
				and cp.id_convenio = c.id
				and c.id_tipo_convenio = tc.id
				and p.id_tipo_procedimento = tp.id 
		SQL;

		$binds = [ 
			'unidade_id' => $unidadeId
		];
		$data = db_connect()->query( $sql, $binds )
			->getResultArray();
		return $this->response->setStatusCode( count( $data ) > 0 ? 200 : 404 )
			->setJSON( [ 
			'message' => 'Dados encontrados com sucesso.',
			'data' => $data
		] );

	}

	public function getProcedimentoByUnidadeByTipoId(int $unidadeId, int $tipoProcedimento) {

		$service = new ProcedimentoService();
		
		$service_response = $service->getProcedimentoByUnidadeByTipoId( $unidadeId, $tipoProcedimento);
		
		$response_messages = [
				ServiceResponseInterface::SUCESS => [
						'code' => ResponseInterface::HTTP_OK,
						'message' => 'A consulta realizada com sucesso.'
				],
				ServiceResponseInterface::HAVE_CONFLICTS => [
						'code' => ResponseInterface::HTTP_CONFLICT,
						'message' => 'Existem confiltos nos parametros de busca'
				],
				ServiceResponseInterface::RECORD_NOT_FOUND => [
						'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
						'message' => 'Nenhum registro foi encontrado.'
				],
				ServiceResponseInterface::RECORD_IS_LINKED => [
						'code' => ResponseInterface::HTTP_BAD_REQUEST,
						'message' => 'Parametros passados insuficientes para realizar a pesquisa.'
				],
				ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [
						'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
						'message' => 'Erro interno do servidor.'
				]
		];
		
		return $this->getResponse( $service_response, $response_messages );
		
// 		$sql = <<<SQL
// 			select
// 				p.id as procedimento_id, p.descricao as procedimento_descricao,
// 				p.id_tipo_procedimento as tipo_procedimento_id ,tp.descricao as tipo_procedimento_descricao,
// 				cp.id_unidade as unidade_id, cp.id as convenio_procedimento_id , cp.id_convenio as convenio_id ,
// 				tc.id tipo_convenio_id, tc.descricao as tipo_convenio_descricao
// 			from
// 				procedimento p , convenio_procedimento cp , tipo_procedimento tp , convenio c , tipo_convenio tc
// 			where
// 				cp.id_unidade = :unidade_id:				
// 				and cp.id_procedimento = p.id
// 				and cp.id_convenio = c.id
// 				and c.id_tipo_convenio = tc.id
// 				and p.id_tipo_procedimento = tp.id
// 				and tp.id = :procedimento_tipo_id:
// 		SQL;

// 		$binds = [ 
// 			'unidade_id' => $unidadeId,
// 			'procedimento_tipo_id' => $tipoProcedimento
// 		];
// 		$data = db_connect()->query( $sql, $binds )
// 			->getResultArray();
// 		return $this->response->setStatusCode( count( $data ) > 0 ? 200 : 404 )
// 			->setJSON( [ 
// 			'message' => 'Dados encontrados com sucesso.',
// 			'data' => $data
// 		] );

	}

	public function getProcedimentoByUnidadeByTipoConvenioId(int $unidadeId, int $tipoConvenio) {

		$service = new ProcedimentoService();
		
		$service_response = $service->getProcedimentoByUnidadeByTipoConvenioId($unidadeId, $tipoConvenio);
		
		$response_messages = [
				ServiceResponseInterface::SUCESS => [
						'code' => ResponseInterface::HTTP_OK,
						'message' => 'A consulta realizada com sucesso.'
				],
				ServiceResponseInterface::HAVE_CONFLICTS => [
						'code' => ResponseInterface::HTTP_CONFLICT,
						'message' => 'Existem confiltos nos parametros de busca'
				],
				ServiceResponseInterface::RECORD_NOT_FOUND => [
						'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
						'message' => 'Nenhum registro foi encontrado.'
				],
				ServiceResponseInterface::RECORD_IS_LINKED => [
						'code' => ResponseInterface::HTTP_BAD_REQUEST,
						'message' => 'Parametros passados insuficientes para realizar a pesquisa.'
				],
				ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [
						'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
						'message' => 'Erro interno do servidor.'
				]
		];
		
		return $this->getResponse( $service_response, $response_messages );
		
// 		$sql = <<<SQL
// 			select
// 				p.id as procedimento_id, p.descricao as procedimento_descricao,
// 				p.id_tipo_procedimento as tipo_procedimento_id ,tp.descricao as tipo_procedimento_descricao,
// 				cp.id_unidade as unidade_id, cp.id as convenio_procedimento_id , cp.id_convenio as convenio_id ,
// 				tc.id tipo_convenio_id, tc.descricao as tipo_convenio_descricao
// 			from
// 				procedimento p , convenio_procedimento cp , tipo_procedimento tp , convenio c , tipo_convenio tc
// 			where
// 				cp.id_unidade = :unidade_id:				
// 				and cp.id_procedimento = p.id
// 				and cp.id_convenio = c.id
// 				and c.id_tipo_convenio = tc.id
// 				and c.id_tipo_convenio = :convenio_tipo_id:
// 				and p.id_tipo_procedimento = tp.id
				
// 		SQL;

// 		$binds = [ 
// 			'unidade_id' => $unidadeId,
// 			'convenio_tipo_id' => $tipoConvenio
// 		];
// 		$data = db_connect()->query( $sql, $binds )
// 			->getResultArray();
// 		return $this->response->setStatusCode( count( $data ) > 0 ? 200 : 404 )
// 			->setJSON( [ 
// 			'message' => 'Dados encontrados com sucesso.',
// 			'data' => $data
// 		] );

	}

	public function getProcedimentoFilteredByUnidadeAndConvenio() {

		$uri = explode( '/', $_SERVER ['REQUEST_URI'] );
		$unidadeId = ( int ) $uri [3] ?? 0;
		$convenioId = ( int ) $uri [5] ?? 0;
		if (!$unidadeId || !$convenioId) {
			return $this->response->setStatusCode( 404 );
		}
		$sql = <<<SQL
		    select
		        p.id as procedimento_id
		        ,p.descricao as procedimento_descricao
		        ,p.id_tipo_procedimento as tipo_procedimento_id
		        ,tp.descricao as tipo_procedimento_descricao
		        ,cp.id_convenio as convenio_id
		        ,cp.id_unidade as unidade_id
		    from procedimento p 
		    inner join convenio_procedimento cp ON cp.id_procedimento = p.id
		    inner join tipo_procedimento tp on tp.id = p.id_tipo_procedimento 
		    where
		        cp.id_convenio = :convenio_id:
		        and cp.id_unidade = :unidade_id:
		        and cp.desativado_em is null
		        and cp.desativado_por is null
		    order by tp.descricao, p.descricao 
		SQL;
		$data = db_connect()->query( $sql, [ 
			'unidade_id' => $unidadeId,
			'convenio_id' => $convenioId
		] )
			->getResultArray();
		return $this->response->setStatusCode( count( $data ) > 0 ? 200 : 404 )
			->setJSON( [ 
			'message' => 'Dados encontrados com sucesso.',
			'data' => $data
		] );

	}

}
