<?php

namespace App\Services;

use App\DAO\DAOResponse\DAOResponseInterface;
use App\DAO\FormularioDAO;
use App\DAO\Pagination\Pagination;
use App\Mappers\FormularioMapper;
use App\Models\FormularioModel;
use App\Services\ServiceResponse\ServiceResponse;
use App\Services\ServiceResponse\ServiceResponseInterface;
use App\Utils\Collections\GeneralCollection;
use App\Utils\Collections\QueryFilterCollection;
use App\Utils\Collections\QueryOrderCollection;
use App\Utils\ResponseException;
use App\ViewModels\Formulario\FormularioDetailsViewModel\FormularioDetailsViewModel;

class FormularioService extends Service {

	public function registerFormulario(array $data_post): ServiceResponse {

		$service_response = new ServiceResponse();
		$jwt_payload = JWTService::getTokenJWTPayload();
		$log_service = new LogService();

		// Verifica erros de validação na construção do objeto de entrada de dados
		try {
			$formulario_registration_vm = FormularioMapper::getFormularioRegistrationVMFromArray( $data_post );
		} catch ( ResponseException $exception ) {
			$service_response->setErrors( $exception->getData() );
			$service_response->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
			return $service_response;
		}

		// // Verifica se o médico solicitante é o mesmo médico envolvido na operação.
		// try {
		// $this->verifyMedicoPermissionForMedicoOperation($formulario_registration_vm->getIdMedico());
		// } catch (ResponseException $exception) {
		// $service_response->setStatus(ServiceResponseInterface::FORBIDDEN);
		// $log_service->log_error(
		// 0,
		// "O médico {$exception->getData()['id_medico_requester']} tentou fazer um cadastro de formulário para o médico
		// {$formulario_registration_vm->getIdMedico()}. Foi impedido.",
		// $data_post
		// );
		// return $service_response;
		// }
		//
		// // Verifica se a assistente solicitante é assistente do médico envolvido na operação.
		// try {
		// $this->verifyAssistentePermissionForMedicoOperation($formulario_registration_vm->getIdMedico());
		// } catch (ResponseException $exception) {
		// $service_response->setStatus(ServiceResponseInterface::FORBIDDEN);
		// $log_service->log_error(
		// 0,
		// "O assistente de usuário {$jwt_payload->getUid()} tentou fazer um cadastro de formulário para o médico {$formulario_registration_vm->getIdMedico()},
		// do qual não é assistente. Foi impedido.",
		// $data_post
		// );
		// return $service_response;
		// }
		$formulario_dao = new FormularioDAO();
		$dao_response = $formulario_dao->registerFormulario( $formulario_registration_vm );
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				break;
			case DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS :
				$service_response->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
				$service_response->setErrors( $dao_response->getErrors() );
				break;
			default :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
		}
		return $service_response;

	}

	public function getFormularioList(int $id_medico, ?Pagination $pagination, QueryFilterCollection $query_filter_collection,
			QueryOrderCollection $query_order_collection): ServiceResponse {

		$service_response = new ServiceResponse();
		$log_service = new LogService();
		try {
			// $this->verifyMedicoPermissionForMedicoOperation($id_medico);
		} catch ( ResponseException $exception ) {
			$log_service->log_error( ServiceResponseInterface::FORBIDDEN,
				"Um médico de id {$exception->getData()['id_medico_requester']} tentou acessar os formulários do médico $id_medico.", [ ] );
			$service_response->setStatus( ServiceResponseInterface::FORBIDDEN );
			return $service_response;
		}
		try {
			$this->verifyAssistentePermissionForMedicoOperation( $id_medico );
		} catch ( ResponseException $exception ) {
			$log_service->log_error( ServiceResponseInterface::FORBIDDEN,
				"Um assistente de id {$exception->getData()['assistente_uid']} tentou acessar os formulários do médico $id_medico, do qual não é assistente",
				[ ] );
			$service_response->setStatus( ServiceResponseInterface::FORBIDDEN );
			return $service_response;
		}
		$formulario_dao = new FormularioDAO();
		$dao_response = $formulario_dao->getFormularioList( $id_medico, $pagination, $query_filter_collection, $query_order_collection );
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				$formulario_listing_vm = (function (GeneralCollection $formulario_listing_vm): GeneralCollection {
					return $formulario_listing_vm;
				})( $dao_response->getData() );
				$formulario_listing_array = FormularioMapper::getFormularioListingArrayFromVM( $formulario_listing_vm );
				$pagination = $dao_response->getPagination();
				$data = [ 
					'formularios' => $formulario_listing_array,
					'pagination' => $pagination ? $pagination->toResponseArray() : null
				];
				$service_response->setData( $data );
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$service_response->setStatus( ServiceResponseInterface::RECORD_NOT_FOUND );
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
		}
		return $service_response;

	}

	public function getAllFormularioList(?Pagination $pagination, QueryFilterCollection $query_filter_collection, QueryOrderCollection $query_order_collection): ServiceResponse {

		$service_response = new ServiceResponse();
		$log_service = new LogService();
		// try {
		// // $this->verifyMedicoPermissionForMedicoOperation($id_medico);
		// } catch (ResponseException $exception) {
		// $log_service->log_error(ServiceResponseInterface::FORBIDDEN,"Um médico de id {$exception->getData()['id_medico_requester']} tentou acessar os
		// formulários do médico $id_medico.",[]);
		// $service_response->setStatus(ServiceResponseInterface::FORBIDDEN);
		// return $service_response;
		// }
		// try {
		// //$this->verifyAssistentePermissionForMedicoOperation($id_medico);
		// } catch (ResponseException $exception) {
		// $log_service->log_error(ServiceResponseInterface::FORBIDDEN,"Um assistente de id {$exception->getData()['assistente_uid']} tentou acessar os
		// formulários do médico $id_medico, do qual não é assistente",[]);
		// $service_response->setStatus(ServiceResponseInterface::FORBIDDEN);
		// return $service_response;
		// }
		$formulario_dao = new FormularioDAO();
		$dao_response = $formulario_dao->getAllFormularioList( $pagination, $query_filter_collection, $query_order_collection );
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				$formulario_listing_vm = (function (GeneralCollection $formulario_listing_vm): GeneralCollection {
					return $formulario_listing_vm;
				})( $dao_response->getData() );
				$formulario_listing_array = FormularioMapper::getFormularioListingArrayFromVM( $formulario_listing_vm );
				$pagination = $dao_response->getPagination();
				$data = [ 
					'formularios' => $formulario_listing_array,
					'pagination' => $pagination ? $pagination->toResponseArray() : null
				];
				$service_response->setData( $data );
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$service_response->setStatus( ServiceResponseInterface::RECORD_NOT_FOUND );
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
		}
		return $service_response;

	}

	public function getFormularioByID(int $id_formulario): ServiceResponse {

		$formulario_dao = new FormularioDAO();
		$log_service = new LogService();
		$dao_response = $formulario_dao->getFormularioDetailsByFormularioID( $id_formulario );
		$service_response = new ServiceResponse();
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				$formulario_details_vm = (function (FormularioDetailsViewModel $formulario_details_vm): FormularioDetailsViewModel {
					return $formulario_details_vm;
				})( $dao_response->getData() );
				$formulario_id_medico = $formulario_details_vm->getIdMedico();
				try {
					// $this->verifyMedicoPermissionForMedicoOperation($formulario_id_medico);
				} catch ( ResponseException $exception ) {
					$log_service->log_error( ServiceResponseInterface::FORBIDDEN,
						"Um médico de id {$exception->getData()['id_medico_requester']} tentou acessar o formulário {$id_formulario}, que pertence ao médico {$formulario_id_medico}. Foi impedico.",
						[ ] );
					$service_response->setStatus( ServiceResponseInterface::FORBIDDEN );
					return $service_response;
				}
				try {
					// $this->verifyAssistentePermissionForMedicoOperation($formulario_id_medico);
				} catch ( ResponseException $exception ) {
					$log_service->log_error( ServiceResponseInterface::FORBIDDEN,
						"Um assistente de id {$exception->getData()['assistente_uid']} tentou acessar um formulário do médico $formulario_id_medico, do qual não é assistente. Foi impedico.",
						[ ] );
					$service_response->setStatus( ServiceResponseInterface::FORBIDDEN );
					return $service_response;
				}
				$service_response->setData( $formulario_details_vm->toArray() );
				break;
			case DAOResponseInterface::RECORD_NOT_FOUND :
				$service_response->setStatus( ServiceResponseInterface::RECORD_NOT_FOUND );
				break;
			default :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
		}
		return $service_response;

	}

	public function updateFormularioData(int $id_formulario, array $data_post): ServiceResponse {

		$jwt_payload = JWTService::getTokenJWTPayload();
		$log_service = new LogService();
		$service_response = new ServiceResponse();
		// Verifica se o formulário já foi respondido
		$formulario_dao = new FormularioDAO();
		$dao_response = $formulario_dao->getFormularioFilledByFormularioID( $id_formulario );
		$status_form = 0;
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				// $service_response->setStatus(ServiceResponseInterface::UNKNOWN_ERROR);
				// return $service_response;
				$status_form = 1;
				break;

			case DAOResponseInterface::RECORD_NOT_FOUND :
				break;
			default :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
		}

		if ($status_form == 0) {
			# Deleta o formulário
			$dao_response = $formulario_dao->getFormularioDeleteByFormularioID( $id_formulario );
			switch ($dao_response->getStatus()) {
				case DAOResponseInterface::SUCESS :
					break;
				case DAOResponseInterface::ERROR_DELETING :
					$service_response->setStatus( ServiceResponseInterface::ERROR_DELETING );
					return $service_response;
				default :
					$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
					break;
			}
		} elseif ($status_form == 1) {
			# Deleta apenas a tabela PROCEDIMENTO_FORMULARIO
			$dao_response = $formulario_dao->getProcedimentoFormularioDeleteByFormularioID( $id_formulario );
			switch ($dao_response->getStatus()) {
				case DAOResponseInterface::SUCESS :
					$status_form = 2;
					break;
				case DAOResponseInterface::ERROR_DELETING :
					$service_response->setStatus( ServiceResponseInterface::ERROR_DELETING );
					return $service_response;
				default :
					$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
					break;
			}
		}

		if ($status_form == 2) {
			$endereco_model = new FormularioModel();
			$sucess_update = $endereco_model->updateStatusFormularioSimpleByID( $id_formulario );
			if ($sucess_update ['message'] != "") {
				$service_response->setStatus( ServiceResponseInterface::ERROR_UPDATE );
				return $service_response;
			}
		}

		// Verifica erros de validação na construção do objeto de entrada de dados
		try {
			$formulario_registration_vm = FormularioMapper::getFormularioRegistrationVMFromArray( $data_post );
		} catch ( ResponseException $exception ) {
			$service_response->setErrors( $exception->getData() );
			$service_response->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
			return $service_response;
		}

		// Verifica se o médico solicitante é o mesmo médico envolvido na operação.
		try {
			// $this->verifyMedicoPermissionForMedicoOperation($formulario_registration_vm->getIdMedico());
		} catch ( ResponseException $exception ) {
			$service_response->setStatus( ServiceResponseInterface::FORBIDDEN );
			$log_service->log_error( 0,
				"O médico {$exception->getData()['id_medico_requester']} tentou fazer um cadastro de formulário para o médico {$formulario_registration_vm->getIdMedico()}. Foi impedido.",
				$data_post );
			return $service_response;
		}

		// Verifica se a assistente solicitante é assistente do médico envolvido na operação.
		try {
			// $this->verifyAssistentePermissionForMedicoOperation($formulario_registration_vm->getIdMedico());
		} catch ( ResponseException $exception ) {
			$service_response->setStatus( ServiceResponseInterface::FORBIDDEN );
			$log_service->log_error( 0,
				"O assistente de usuário {$jwt_payload->getUid()} tentou fazer um cadastro de formulário para o médico {$formulario_registration_vm->getIdMedico()}, do qual não é assistente. Foi impedido.",
				$data_post );
			return $service_response;
		}
		$formulario_dao = new FormularioDAO();
		$dao_response = $formulario_dao->registerFormulario( $formulario_registration_vm );
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				break;
			case DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS :
				$service_response->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
				$service_response->setErrors( $dao_response->getErrors() );
				break;
			default :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
		}
		return $service_response;

	}

	public function updateFormularioSimpleData(int $id_formulario, array $data): ServiceResponse {

		$formulario_update_vm = FormularioMapper::getFormularioSimpleUpdateVMFromArray( $data );
		$formulario_dao = new FormularioDAO();
		$dao_response = $formulario_dao->persistFormularioSimpleUpdateVM( $id_formulario, $formulario_update_vm );
		$service_response = new ServiceResponse();
		$response_status = [ 
			DAOResponseInterface::SUCESS => ServiceResponseInterface::SUCESS,
			DAOResponseInterface::RECORD_NOT_FOUND => ServiceResponseInterface::RECORD_NOT_FOUND,
			DAOResponseInterface::DATABASE_CONNECTION_ERROR => ServiceResponseInterface::DATABASE_CONNECTION_ERROR,
			DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS => ServiceResponseInterface::VALIDATION_PARAMS_ERROR,
			DAOResponseInterface::DUPLICATED_UNIQUE_KEY => ServiceResponseInterface::VALIDATION_PARAMS_ERROR
		] [$dao_response->getStatus()];
		if (!$response_status) {
			(new LogService())->log_error( $response_status, "Ocorreu um erro desconhecido durante a atualização o procedimento", [ ] );
			$response_status = ServiceResponseInterface::DATABASE_CONNECTION_ERROR;
		} else if ($response_status !== ServiceResponseInterface::SUCESS) {
			$service_response->setErrors( $dao_response->getErrors() );
		}
		$service_response->setStatus( $response_status );
		return $service_response;

	}

	public function desativaFormulario(int $id_formulario): ServiceResponse {

		$formulario_dao = new FormularioDAO();
		$dao_response = $formulario_dao->persistFormularioDesativaVM( $id_formulario );
		$service_response = new ServiceResponse();
		switch ($dao_response->getStatus()) {
			case DAOResponseInterface::SUCESS :
				$service_response->setStatus( ServiceResponseInterface::SUCESS );
				break;
			case DAOResponseInterface::DUPLICATED_UNIQUE_KEY :
			case DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS :
				$service_response->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
				$service_response->setErrors( $dao_response->getErrors() );
				break;
			case DAOResponseInterface::DATABASE_CONNECTION_ERROR :
				$service_response->setStatus( ServiceResponseInterface::DATABASE_CONNECTION_ERROR );
				break;
		}
		return $service_response;

	}

	public function getListFormulariosByProcedimentoId(int $idProcedimento): ServiceResponse {

		$dao = new FormularioDAO();
		$service_response = new ServiceResponse();
		$dao_response = $dao->getListFormulariosByProcedimentoId( $idProcedimento );
		$service_response = $this->setServiceResponse( $dao_response );

		return $service_response;

	}

    public function getListFormulariosByAtendimento(): ServiceResponse {

        $dao = new FormularioDAO();
        $service_response = new ServiceResponse();
        $dao_response = $dao->getListFormulariosByAtendimento();
        $service_response = $this->setServiceResponse( $dao_response );

        return $service_response;

    }

	public function getReformatRespostasFormulario(array $perguntas, array $respostas): ServiceResponse {

		$service_response = new ServiceResponse();

		for($i = 0; $i < count( $perguntas ); $i++) {
			if (count( $respostas ) > 0) {
				$tem = 0;
				for($y = 0; $y < count( $respostas ); $y++) {
					if ($perguntas [$i] ['id'] == $respostas [$y] ['id_pergunta']) {
						$tem = 1;
					}
				}

				if ($tem == 0) {
					$arr = [ 
						'id_pergunta' => $perguntas [$i] ['id'],
						'resposta' => ''
					];
					array_push( $respostas, $arr );
				}
			} else {
				$arr_2 = [ 
					'id_pergunta' => $perguntas [$i] ['id'],
					'resposta' => ''
				];
				array_push( $respostas, $arr_2 );
			}
		}

		$service_response->setData( [ 
			'respostas' => $respostas
		] );
		
		$service_response->setStatus(ServiceResponseInterface::SUCESS);

		return $service_response;

	}

}