<?php

namespace App\Mappers;

use App\Entities\Formulario\Formulario;
use App\Entities\Pergunta\Pergunta;
use App\Entities\ProcedimentoFormulario\ProcedimentoFormulario;
use App\Services\JWTService;
use App\Utils\Collections\GeneralCollection;
use App\Utils\DateUtils;
use App\Utils\ResponseException;
use App\ViewModels\Formulario\FormularioDetailsViewModel\FormularioDetailsResponseDatabase;
use App\ViewModels\Formulario\FormularioDetailsViewModel\FormularioDetailsViewModel;
use App\ViewModels\Formulario\FormularioDetailsViewModel\OpcaoDetails;
use App\ViewModels\Formulario\FormularioDetailsViewModel\OpcaoDetailsCollection;
use App\ViewModels\Formulario\FormularioDetailsViewModel\PerguntaDetails;
use App\ViewModels\Formulario\FormularioDetailsViewModel\PerguntaDetailsCollection;
use App\ViewModels\Formulario\FormularioListingViewModel\FormularioListingViewModel;
use App\ViewModels\Formulario\FormularioRegistrationViewModel\FormularioRegistrationViewModel;
use App\ViewModels\Formulario\FormularioRegistrationViewModel\PerguntaRegistration;
use App\ViewModels\Formulario\FormularioRegistrationViewModel\PerguntaRegistrationCollection;
use App\ViewModels\Formulario\FormularioUpdateViewModel\FormularioUpdateViewModel;
use App\ViewModels\Formulario\FormularioUpdateViewModel\PerguntaUpdate;
use App\ViewModels\Formulario\FormularioUpdateViewModel\PerguntaUpdateCollection;
use App\ViewModels\Formulario\PerguntaDetailsViewModel\PerguntaDetailsViewModel;
use App\ViewModels\Formulario\PerguntaOpcoesViewModel\PerguntaOpcoesViewModel;
// use phpDocumentor\Reflection\Types\Collection;
use function Sodium\add;

class FormularioMapper {

	public static function getFormularioRegistrationVMFromArray(array $data_post): FormularioRegistrationViewModel {

		$pergunta_registration_collection = new PerguntaRegistrationCollection();
		foreach ( $data_post ['perguntas'] as $pergunta ) {
			$pergunta_registration_collection->push( 
					PerguntaRegistration::builder()->setIdTipoPergunta( $pergunta ['id_tipo_pergunta'] )
						->setObrigatorio( $pergunta ['obrigatorio'] )
						->setTextoPergunta( $pergunta ['texto_pergunta'] )
						->setOpcoes( $pergunta ['opcoes'] ?? [ ])
						->setOrdem( $pergunta ['ordem'] ?? 0)
						->setAtivo( $pergunta ['ativo'] ?? 1)
						->build() );
		}
		$formulario_registration_vm = FormularioRegistrationViewModel::builder()->setAtivo( 1 )
			->setIdMedico( $data_post ['id_medico'] )
			->setDescricao( $data_post ['descricao'] )
			->setTitulo( $data_post ['titulo'] )
			->setPerguntas( $pergunta_registration_collection )
			->setProcedimentos( $data_post ['procedimentos'] ?? [ ])
			->setAtendimento( $data_post ['atendimento'] ?? false)
			->build();
		return $formulario_registration_vm;

	}

	public static function getFormularioFromFormularioRegistrationVM(FormularioRegistrationViewModel $formulario_registration_vm): Formulario {

		$jwt_payload = JWTService::getTokenJWTPayload();
		$formulario = Formulario::builder()->setTitulo( $formulario_registration_vm->getTitulo() )
			->setDescricao( $formulario_registration_vm->getDescricao() )
			->setIdMedico( null )
			->setAtivo( $formulario_registration_vm->getAtivo() )
			->setCriadoPor( $jwt_payload->getUid() )
			->build();
		// ->setIdMEDICO($formulario_registration_vm->getIdMedico())
		return $formulario;

	}

	public static function getPerguntaFromFormularioRegistrationVM(Formulario $formulario, PerguntaRegistration $pergunta_registration): Pergunta {

		return Pergunta::builder()->setTextoPergunta( $pergunta_registration->getTextoPergunta() )
			->setObrigatorio( $pergunta_registration->getObrigatorio() )
			->setIdFormulario( $formulario->getId() )
			->setIdTipoPergunta( $pergunta_registration->getIdTipoPergunta() )
			->setOrdem( $pergunta_registration->getOrdem() ?? 0)
			->setAtivo( $pergunta_registration->getAtivo() ?? 1)
			->build();

	}

	public static function getFormularioListingVMFromArray(array $formulario): FormularioListingViewModel {

		return FormularioListingViewModel::builder()->setDescricao( $formulario ['descricao'] )
			->setId( $formulario ['id'] )
			->setTitulo( $formulario ['titulo'] )
			->setAtivo( $formulario ['ativo'] )
			->setQuantidadePerguntas( $formulario ['quantidade_perguntas'] )
			->build();

	}

	public static function getFormularioListingVMCollectionFromArray(array $result_array): GeneralCollection {

		$formulario_listing_vm_collection = new GeneralCollection();
		foreach ( $result_array as $row ) {
			$formulario_listing_vm_collection->push( self::getFormularioListingVMFromArray( $row ) );
		}
		return $formulario_listing_vm_collection;

	}

	public static function getFormularioListingArrayFromVM(GeneralCollection $formulario_listing_vm): array {

		return $formulario_listing_vm->toArray();

	}

	public static function getFormularioDetailsVMFromArray(array $response_array): FormularioDetailsViewModel {

		$formulario_details_vm = new FormularioDetailsViewModel();
		$array = array ();
		foreach ( $response_array as $value ) {
			array_push( $array, $value ["formulario_procedimentos"] );
		}
		$teste = array_values( array_unique( $array ) );

		$formulario_details_response_db_collection = (new GeneralCollection( $response_array ))->map( 
				function (array $row): FormularioDetailsResponseDatabase {
					return FormularioDetailsResponseDatabase::builder()->setFormularioTitulo( $row ['formulario_titulo'] )
						->setFormularioAtivo( $row ['formulario_ativo'] )
						->setFormularioDescricao( $row ['formulario_descricao'] )
						->setFormularioIdMedico( $row ['formulario_id_medico'] )
						->setFormularioProcedimentos( $row ['formulario_procedimentos'] ?? [ ])
						->setFormularioAtendimentoId( $row ['formulario_atendimento_id'])
						->setPerguntaId( $row ['pergunta_id'] )
						->setPerguntaOrdem( $row ['ordem'] ?? 0)
						->setPerguntaAtivo( $row ['ativo'] ?? 1)
						->setPerguntaTextoPergunta( $row ['pergunta_texto_pergunta'] )
						->setPerguntaIdTipoPergunta( $row ['pergunta_id_tipo_pergunta'] )
						->setPerguntaObrigatorio( $row ['pergunta_obrigatorio'] )
						->setOpcaoPerguntaId( $row ['opcao_pergunta_id'] )
						->setOpcaoPerguntaDescricao( $row ['opcao_pergunta_descricao'] )
						->setOpcaoPerguntaIdPergunta( $row ['opcao_pergunta_id_pergunta'] )
						->build();
				} );

		$first_row = (function (FormularioDetailsResponseDatabase $formulario_details_response_db): FormularioDetailsResponseDatabase {
			return $formulario_details_response_db;
		})( $formulario_details_response_db_collection->get( 0 ) );
		$formulario_details_vm->setTitulo( $first_row->getFormularioTitulo() );
		$formulario_details_vm->setAtivo( $first_row->getFormularioAtivo() );
		$formulario_details_vm->setDescricao( $first_row->getFormularioDescricao() );
		$formulario_details_vm->setIdMedico( $first_row->getFormularioIdMedico() );
		$formulario_details_vm->setAtendimento($first_row->getFormularioAtendimentoId() != null);
		$formulario_details_vm->setProcedimentos( $teste );

		$pergunta_details_collection = new PerguntaDetailsCollection();
		$formulario_details_response_db_collection->forEach( 
				function (FormularioDetailsResponseDatabase $formulario_details_response_db) use ($pergunta_details_collection): void {
					$pergunta_already_exists = $pergunta_details_collection->some( 
							function (PerguntaDetails $pergunta_details) use ($formulario_details_response_db) {
								return $pergunta_details->getId() === $formulario_details_response_db->getPerguntaId();
							} );
					if (!$pergunta_already_exists) {
						$pergunta_details = PerguntaDetails::builder()->setId( $formulario_details_response_db->getPerguntaId() )
							->setTextoPergunta( $formulario_details_response_db->getPerguntaTextoPergunta() )
							->setIdTipoPergunta( $formulario_details_response_db->getPerguntaIdTipoPergunta() )
							->setObrigatorio( $formulario_details_response_db->getPerguntaObrigatorio() )
							->setOpcoes( new OpcaoDetailsCollection() )
							->setOrdem( $formulario_details_response_db->getPerguntaOrdem() ?? 0)
							->setAtivo( $formulario_details_response_db->getPerguntaAtivo() ?? 1)
							->build();
						$pergunta_details_collection->push( $pergunta_details );
					}
				} );

		$pergunta_details_collection->map( 
				function (PerguntaDetails $pergunta_details) use ($formulario_details_response_db_collection): PerguntaDetails {
					$opcoes_collection = $pergunta_details->getOpcoes();
					$formulario_details_response_db_collection->forEach( 
							function (FormularioDetailsResponseDatabase $formulario_details_response_db) use ($opcoes_collection, $pergunta_details): void {
								$pergunta_already_exists = $opcoes_collection->some( 
										function (OpcaoDetails $opcao_details) use ($formulario_details_response_db) {
											return $opcao_details->getId() === $formulario_details_response_db->getOpcaoPerguntaId();
										} );
								if ($pergunta_details->getId() === $formulario_details_response_db->getOpcaoPerguntaIdPergunta()) {
									if (!$pergunta_already_exists) {
										$opcoes_collection->push( 
												OpcaoDetails::builder()->setId( $formulario_details_response_db->getOpcaoPerguntaId() )
													->setDescricao( $formulario_details_response_db->getOpcaoPerguntaDescricao() )
													->build() );
									}
								}
							} );
					$pergunta_details->setOpcoes( $opcoes_collection );
					return $pergunta_details;
				}, true );
		$formulario_details_vm->setPerguntas( $pergunta_details_collection );

		return $formulario_details_vm;

	}

	public static function getPerguntaDetailsVMFromArray(array $pergunta): PerguntaDetailsViewModel {

		return PerguntaDetailsViewModel::builder()->setIdPergunta( $pergunta ['id_pergunta'] )
			->setObrigatorio( !!$pergunta ['obrigatorio'] )
			->setIdTipoPergunta( $pergunta ['id_tipo_pergunta'] )
			->setOrdem($pergunta ['ordem'] ?? 0)
			->setAtivo($pergunta ['ativo'] ?? 1)
			->build();

	}

	public static function getPerguntaDetailsVMCollectionFromArray(array $response_array): GeneralCollection {

		$pergunta_details_vm_collection = new GeneralCollection();
		foreach ( $response_array as $row ) {
			$pergunta_details_vm = self::getPerguntaDetailsVMFromArray( $row );
			$pergunta_details_vm_collection->push( $pergunta_details_vm );
		}
		return $pergunta_details_vm_collection;

	}

	public static function getPerguntaOpcoesVMFromArray(array $row): PerguntaOpcoesViewModel {

		return PerguntaOpcoesViewModel::builder()->setIdPergunta( $row ['id_pergunta'] )
			->setIdOpcaoPergunta( $row ['id_opcao_pergunta'] )
			->build();

	}

	public static function getPerguntaOpcoesVMCollectionFromArray(array $response_array): GeneralCollection {

		$pergunta_opcoes_vm = new GeneralCollection();
		foreach ( $response_array as $row ) {
			$pergunta_opcoes_vm->push( self::getPerguntaOpcoesVMFromArray( $row ) );
		}
		return $pergunta_opcoes_vm;

	}

	public static function getFormularioSimpleUpdateVMFromArray(array $data): FormularioUpdateViewModel {

		$formulario_update_vm = new FormularioUpdateViewModel();
		if (isset( $data ['titulo'] )) {
			$formulario_update_vm->setTitulo( $data ['titulo'] );
		}
		if (isset( $data ['descricao'] )) {
			$formulario_update_vm->setDescricao( $data ['descricao'] );
		}
		if (isset( $data ['id_medico'] )) {
			$formulario_update_vm->setIdMedico( $data ['id_medico'] );
		}
		return $formulario_update_vm;

	}

	public static function getFormularioSimpleFromFormularioUpdateVM(FormularioUpdateViewModel $formulario_update_vm): Formulario {

		$procedimento = new Formulario();
		if ($formulario_update_vm->getTitulo()) {
			$procedimento->setTitulo( $formulario_update_vm->getTitulo() );
		}
		if ($formulario_update_vm->getDescricao()) {
			$procedimento->setDescricao( $formulario_update_vm->getDescricao() );
		}
		if ($formulario_update_vm->getIdMedico()) {
			$procedimento->setIdMedico( $formulario_update_vm->getIdMedico() );
		}
		return $procedimento;

	}

}