<?php

namespace App\Mappers;

use App\DAO\MedicoDAO;
use App\Entities\CEP\CEP;
use App\Entities\Cliente\Cliente;
use App\Entities\ConfirmacaoEmail\ConfirmacaoEmail;
use App\Entities\Endereco\Endereco;
use App\Entities\Medico\Medico;
use App\Entities\Paciente\Paciente;
use App\Entities\Pessoa\Pessoa;
use App\Entities\PessoaFisica\PessoaFisica;
use App\Entities\Profissional\Profissional;
use App\Entities\ProfissionalClinica\ProfissionalClinica;
use App\Entities\Usuario\Usuario;
use App\Entities\UsuarioPerfil\UsuarioPerfil;
use App\Services\JWTService;
use App\Utils\Collections\GeneralCollection;
use App\Utils\DateUtils;
use App\ViewModels\Medico\MedicoDetailsViewModel\MedicoDetailsViewModel;
use App\ViewModels\Medico\MedicoRegistrationViewModel\MedicoRegistrationViewModel;
use App\ViewModels\Medico\MedicoUpdateViewModel\MedicoUpdateViewModel;
use App\Services\JWT\UsuarioLogado;

class MedicoMapper {

	public static function MedicoRegistrationViewModelMapper(array $medico, $file_dir): MedicoRegistrationViewModel {

		$jwt_payload = JWTService::getTokenJWTPayload();
		$uid = $jwt_payload ? $jwt_payload->getUid() : null;
		$medico_registration_vm = MedicoRegistrationViewModel::builder()->setFoto( $medico ['foto'] )
			->setNome( ucwords( $medico ['nome'] ) )
			->setEmail( $medico ['email'] )
			->setRg( $medico ['rg'] )
			->setGenero( $medico ['genero'] )
			->setDataNascimento( $medico ['data_nascimento'] )
			->setEstadoCivil( $medico ['estado_civil'] )
			->setCep( $medico ['cep'] )
			->setNumero( $medico ['numero'] )
			->setComplemento( $medico ['complemento'] )
			->setReferencias( $medico ['referencias'] )
			->setCpf( $medico ['cpf'] )
			->setTelefone1( $medico ['telefone_1'] )
			->setTelefone2( $medico ['telefone_2'] )
			->setAdicionadoPor( $uid )
			->setProfissao( $medico ['profissao'] )
			->setIndicadoPor( $uid )
			->setSenha( $medico ['senha'] )
			->setAtivo( $medico ['ativo'] )
			->setTokenConfirmacaoEmail( $medico ['token_confirmacao_email'] )
			->setCidade( $medico ['cidade'] )
			->setEstado( $medico ['estado'] )
			->setBairro( $medico ['bairro'] )
			->setLogradouro( $medico ['logradouro'] )
			->setSenhaChameFacil( $medico ['senha_chamefacil'] )
			->setAssinatura( $file_dir ?? '')
			->setDocumento( $medico ['documento'] ?? '')
			->setUnidade( $medico ['unidade'] )
			->build();
		return $medico_registration_vm;

	}

	// DETALHES
	public static function getMedicoDetailsVMFromArray(array $medico): MedicoDetailsViewModel {

		if (file_exists( $medico ['foto'] ) === true) {
			$get_file = file_get_contents( $medico ['foto'] );
			$ext = pathinfo( $medico ['foto'], PATHINFO_EXTENSION );
			$filebase64 = base64_encode( $get_file );
		} else {
			$get_file = file_get_contents( "../writable/perfil/default.png" );
			$ext = "png";
			$filebase64 = base64_encode( $get_file );
		}

		$medico_unidades = new MedicoDAO();
		$response_unidades = $medico_unidades->getUnidadesMedico( $medico ['id'] );

		$medico_details_vm = MedicoDetailsViewModel::builder()->setId( $medico ['id'] )
			->setCpf( $medico ['cpf'] )
			->setRg( $medico ['rg'] )
			->setNome( $medico ['nome'] )
			->setGenero( $medico ['genero'] )
			->setDataNascimento( $medico ['data_nascimento'] )
			->setTelefone1( $medico ['telefone_1'] )
			->setTelefone2( $medico ['telefone_2'] )
			->setCep( $medico ['cep'] )
			->setNumero( $medico ['numero'] )
			->setComplemento( $medico ['complemento'] )
			->setReferencias( $medico ['referencias'] )
			->setEstado( $medico ['estado'] )
			->setCidade( $medico ['cidade'] )
			->setBairro( $medico ['bairro'] )
			->setLogradouro( $medico ['logradouro'] )
			->setEmail( $medico ['email'] )
			->setFoto( $filebase64 ?? [ ])
			->setAtivo( $medico ['ativo'] )
			->setProfissao( $medico ['profissao'] ?? '')
			->setEstadoCivil( $medico ['estado_civil'] )
			->setClinica( $response_unidades )
			->setDocumento( $medico ['documento'] ?? '')
			->setTipo( $ext )
			->build();
		return $medico_details_vm;

	}

	public static function getMedicoDetailsVMListFromArray(array $medico_list): GeneralCollection {

		$medico_details_vm_collection = new GeneralCollection();
		for($i = 0, $number_assistentes = count( $medico_list ); $i < $number_assistentes; $i++) {
			$medico_details_vm_collection->push( MedicoMapper::getMedicoDetailsVMFromArray( $medico_list [$i] ) );
		}
		return $medico_details_vm_collection;

	}

	// LISTAGEM
	public static function getMedicoVMFromListArray(array $medico): MedicoDetailsViewModel {

		$medico_unidades = new MedicoDAO();
		$response_unidades = $medico_unidades->getUnidadesMedico( $medico ['id'] );

		$medico_details_vm = MedicoDetailsViewModel::builder()->setId( $medico ['id'] )
			->setCpf( $medico ['cpf'] )
			->setRg( $medico ['rg'] )
			->setNome( $medico ['nome'] )
			->setGenero( $medico ['genero'] )
			->setDataNascimento( $medico ['data_nascimento'] )
			->setTelefone1( $medico ['telefone_1'] )
			->setTelefone2( $medico ['telefone_2'] )
			->setCep( $medico ['cep'] )
			->setNumero( $medico ['numero'] )
			->setComplemento( $medico ['complemento'] )
			->setReferencias( $medico ['referencias'] )
			->setEstado( $medico ['estado'] )
			->setCidade( $medico ['cidade'] )
			->setBairro( $medico ['bairro'] )
			->setLogradouro( $medico ['logradouro'] )
			->setEmail( $medico ['email'] )
			->setFoto( $filebase64 ?? [ ])
			->setAtivo( $medico ['ativo'] )
			->setAtivoDescricao( $medico ['ativo_desc'] ?? '-')
			->setProfissao( $medico ['profissao'] ?? '')
			->setEstadoCivil( $medico ['estado_civil'] )
			->setClinica( $response_unidades )
			->setDocumento( $medico ['documento'] ?? '')
			->setTipo( "" )
			->build();
		return $medico_details_vm;

	}

	public static function getMedicoVMListFromArray(array $medico_list): GeneralCollection {

		$medico_details_vm_collection = new GeneralCollection();
		for($i = 0, $number_assistentes = count( $medico_list ); $i < $number_assistentes; $i++) {
			$medico_details_vm_collection->push( MedicoMapper::getMedicoVMFromListArray( $medico_list [$i] ) );
		}
		return $medico_details_vm_collection;

	}

	public static function getMedicoDetailsArrayFromMedicoDetailsVMList(GeneralCollection $paciente_details_vm_collection): array {

		return $paciente_details_vm_collection->toArray();

	}

	public static function getCepFromMedicoRegistrationVM(MedicoRegistrationViewModel $medico_registration_vm): CEP {

		$endereco = CEP::builder()->setCep( $medico_registration_vm->getCep() )
			->setEstado( $medico_registration_vm->getEstado() )
			->setBairro( $medico_registration_vm->getBairro() )
			->setCidade( $medico_registration_vm->getCidade() )
			->setLogradouro( $medico_registration_vm->getLogradouro() )
			->build();
		return $endereco;

	}

	public static function getEnderecoFromMedicoRegistrationVM(MedicoRegistrationViewModel $medico_registration_vm, CEP $cep): Endereco {

		$endereco = Endereco::builder()->setCep( $cep->getId() )
			->setNumero( $medico_registration_vm->getNumero() )
			->setComplemento( $medico_registration_vm->getComplemento() )
			->setReferencias( $medico_registration_vm->getReferencias() )
			->build();
		return $endereco;

	}

	public static function getPessoaFromMedicoRegistrationVM(MedicoRegistrationViewModel $medico_registration_vm, Endereco $endereco): Pessoa {

		$pessoa = Pessoa::builder()->setTelefone1( $medico_registration_vm->getTelefone1() )
			->setTelefone2( $medico_registration_vm->getTelefone2() )
			->setIdEndereco( $endereco->getId() )
			->setIdTipoPessoa( PESSOA_FISICA_ID )
			->setAdicionadoPor( $medico_registration_vm->getAdicionadoPor() )
			->build();
		return $pessoa;

	}

	public static function getPessoaFisicaFromMedicoRegistrationVM(MedicoRegistrationViewModel $medico_registration_vm, Pessoa $pessoa): PessoaFisica {

		$pessoa_fisica = PessoaFisica::builder()->setIdPessoa( $pessoa->getId() )
			->setCpf( $medico_registration_vm->getCpf() )
			->setRg( $medico_registration_vm->getRg() )
			->setGenero( $medico_registration_vm->getGenero() )
			->setDataNascimento( $medico_registration_vm->getDataNascimento() )
			->setNome( $medico_registration_vm->getNome() )
			->setProfissao( $medico_registration_vm->getProfissao() )
			->setEstadoCivil( $medico_registration_vm->getEstadoCivil() )
			->build();
		return $pessoa_fisica;

	}

	public static function getUsuarioFromMedicoRegistrationVM(MedicoRegistrationViewModel $medico_registration_vm, Pessoa $pessoa): Usuario {

		$usuario = Usuario::builder()->setEmail( $medico_registration_vm->getEmail() )
			->setSenha( $medico_registration_vm->getSenha() )
			->setAtivo( $medico_registration_vm->getAtivo() )
			->setFoto( $medico_registration_vm->getFoto() ?? '')
			->setEmailVerificadoEm( $medico_registration_vm->getTokenConfirmacaoEmail() ? null : DateUtils::now() )
			->setIdPessoa( $pessoa->getId() )
			->setAdicionadoPor( $medico_registration_vm->getAdicionadoPor() )
			->setSenhaChameFacil( $medico_registration_vm->getSenhaChameFacil() )
			->build();
		return $usuario;

	}

	public static function getClienteFromMedicoRegistrationVM(MedicoRegistrationViewModel $medico_registration_vm, Pessoa $pessoa): Cliente {

		$cliente = Cliente::builder()->setAdicionadoPor( $medico_registration_vm->getAdicionadoPor() )
			->setIdPessoa( $pessoa->getId() )
			->build();
		return $cliente;

	}

	public static function getConfirmacaoEmailFromMedicoRegistrationVM(MedicoRegistrationViewModel $medico_registration_vm, Usuario $usuario): ConfirmacaoEmail {

		$confirmacao_email = ConfirmacaoEmail::builder()->setIdUsuario( $usuario->getId() )
			->setToken( $medico_registration_vm->getTokenConfirmacaoEmail() )
			->setTempoExpiracao( EMAIL_TOKEN_EXPIRATION_TIME )
			->build();
		return $confirmacao_email;

	}

	public static function getUsuarioPerfilFromMedicoRegistrationVM(MedicoRegistrationViewModel $medico_registration_vm, Usuario $usuario): UsuarioPerfil {

		$usuario_perfil = UsuarioPerfil::builder()->setIdUsuario( $usuario->getId() )
			->setIdPerfil( PERFIL_MEDICO )
			->build();
		return $usuario_perfil;

	}

	public static function getProfissionalFromMedicoRegistrationVM(MedicoRegistrationViewModel $medico_registration_vm, Pessoa $pessoa): Profissional {

		$profissional = Profissional::builder()->setAdicionadoPor( $medico_registration_vm->getAdicionadoPor() )
			->setIdPessoa( $pessoa->getId() )
			->build();
		return $profissional;

	}

	public static function getProfissionalClinicaFromProfissionalClinicaRegistrationVM(MedicoRegistrationViewModel $medico_registration_vm, Profissional $pessoa,
			$unidade): ProfissionalClinica {

		$profissional_clinica = ProfissionalClinica::builder()->setIdProfissional( $pessoa->getId() )
			->setIdPessoaJuridica( $unidade )
			->build();
		return $profissional_clinica;

	}

	public static function getMedicoFromMedicoRegistrationVM(MedicoRegistrationViewModel $medico_registration_vm, Profissional $pessoa): Medico {

		$medico = Medico::builder()->setIdProfissional( $pessoa->getId() )
			->setAssinatura( $medico_registration_vm->getAssinatura() )
			->setDocumento( $medico_registration_vm->getDocumento() )
			->build();
		return $medico;

	}

	public static function getMedicoUpdateVMFromArray(array $medico_data, $file_dir): MedicoUpdateViewModel {

		$medico_update_vm = new MedicoUpdateViewModel();
		if (isset( $medico_data ['cpf'] )) {
			$medico_update_vm->setCpf( $medico_data ['cpf'] );
		}
		if (isset( $medico_data ['rg'] )) {
			$medico_update_vm->setRg( $medico_data ['rg'] );
		}
		if (isset( $medico_data ['nome'] )) {
			$medico_update_vm->setNome( ucwords( $medico_data ['nome'] ) );
		}
		if (isset( $medico_data ['ativo'] )) {
			$medico_update_vm->setAtivo( $medico_data ['ativo'] );
		}
		if (isset( $medico_data ['ativo_desc'] )) {
			$medico_update_vm->setAtivo( $medico_data ['ativo_desc'] );
		}
		if (isset( $medico_data ['genero'] )) {
			$medico_update_vm->setGenero( $medico_data ['genero'] );
		}
		if (isset( $medico_data ['data_nascimento'] )) {
			$medico_update_vm->setDataNascimento( $medico_data ['data_nascimento'] );
		}
		if (isset( $medico_data ['telefone_1'] )) {
			$medico_update_vm->setTelefone1( $medico_data ['telefone_1'] );
		}
		if (isset( $medico_data ['telefone_2'] )) {
			$medico_update_vm->setTelefone2( $medico_data ['telefone_2'] );
		}
		if (isset( $medico_data ['cep'] )) {
			$medico_update_vm->setCep( $medico_data ['cep'] );
		}
		if (isset( $medico_data ['numero'] )) {
			$medico_update_vm->setNumero( $medico_data ['numero'] );
		}
		if (isset( $medico_data ['complemento'] )) {
			$medico_update_vm->setComplemento( $medico_data ['complemento'] );
		}
		if (isset( $medico_data ['referencias'] )) {
			$medico_update_vm->setReferencias( $medico_data ['referencias'] );
		}
		if (isset( $_FILES ['foto'] )) {
			$ext = "." . pathinfo( $_FILES ['foto'] ['name'], PATHINFO_EXTENSION );
			// $ext = strtolower(substr($_FILES['foto']['name'], -4)); //Pegando extensão do arquivo
			$new_name = date( "Y.m.d-H.i.s" ) . $ext; // Definindo um novo nome para o arquivo
			$dir = '../writable/perfil/';
			move_uploaded_file( $_FILES ['foto'] ['tmp_name'], $dir . $new_name ); // Fazer upload do arquivo
			$medico_data ['foto'] = $dir . $new_name;
		}

		if (isset( $medico_data ['foto'] )) {
			$medico_update_vm->setFoto( $medico_data ['foto'] );
		}
		if (isset( $medico_data ['profissao'] )) {
			$medico_update_vm->setProfissao( $medico_data ['profissao'] );
		}
		if (isset( $medico_data ['documento'] )) {
			$medico_update_vm->setDocumento( $medico_data ['documento'] );
		}
		if (isset( $medico_data ['estado_civil'] )) {
			$medico_update_vm->setEstadoCivil( $medico_data ['estado_civil'] );
		}
		if (isset( $medico_data ['id_medico'] )) {
			$medico_update_vm->setIdMedico( $medico_data ['id_medico'] );
		}

		if (isset( $medico_data ['bairro'] )) {
			$medico_update_vm->setBairro( $medico_data ['bairro'] );
		}
		if (isset( $medico_data ['cidade'] )) {
			$medico_update_vm->setCidade( $medico_data ['cidade'] );
		}
		if (isset( $medico_data ['estado'] )) {
			$medico_update_vm->setEstado( $medico_data ['estado'] );
		}
		if (isset( $medico_data ['logradouro'] )) {
			$medico_update_vm->setLogradouro( $medico_data ['logradouro'] );
		}

		if (isset( $medico_data ['assinatura'] )) {
			$medico_update_vm->setAssinatura( $file_dir );
		}

		if (isset( $medico_data ['senha'] )) {
			if (strlen( trim( $medico_data ['senha'] ) ) > 0) {
				$medico_update_vm->setSenha( trim( $medico_data ['senha'] ) );
			}
		}

		$medico_update_vm->setIndicadoPor( JWTService::getTokenJWTPayload()->getUid() );
		$medico_update_vm->setAlteradoPor( JWTService::getTokenJWTPayload()->getUid() );
		return $medico_update_vm;

	}

	public static function getCepFromMedicoUpdateVM(MedicoUpdateViewModel $medico_update_vm): CEP {

		$endereco = new CEP();
		if ($medico_update_vm->getCep()) {
			$endereco->setCep( $medico_update_vm->getCep() );
		}
		if ($medico_update_vm->getLogradouro()) {
			$endereco->setLogradouro( $medico_update_vm->getLogradouro() );
		}
		if ($medico_update_vm->getCidade()) {
			$endereco->setCidade( $medico_update_vm->getCidade() );
		}
		if ($medico_update_vm->getEstado()) {
			$endereco->setEstado( $medico_update_vm->getEstado() );
		}
		if ($medico_update_vm->getBairro()) {
			$endereco->setBairro( $medico_update_vm->getBairro() );
		}

		return $endereco;

	}

	public static function getEnderecoFromMedicoUpdateVM(MedicoUpdateViewModel $medico_update_vm): Endereco {

		$endereco = new Endereco();
		if ($medico_update_vm->getNumero()) {
			$endereco->setNumero( $medico_update_vm->getNumero() );
		}
		if ($medico_update_vm->getComplemento()) {
			$endereco->setComplemento( $medico_update_vm->getComplemento() );
		}
		if ($medico_update_vm->getReferencias()) {
			$endereco->setReferencias( $medico_update_vm->getReferencias() );
		}
		return $endereco;

	}

	public static function getPessoaFromMedicoUpdateVM(MedicoUpdateViewModel $medico_update_vm): Pessoa {

		$pessoa = new Pessoa();
		if ($medico_update_vm->getTelefone1()) {
			$pessoa->setTelefone1( $medico_update_vm->getTelefone1() );
		}
		if ($medico_update_vm->getTelefone2()) {
			$pessoa->setTelefone2( $medico_update_vm->getTelefone2() );
		}
		if ($medico_update_vm->getAlteradoPor()) {
			$pessoa->setAlteradoPor( $medico_update_vm->getAlteradoPor() );
		}
		return $pessoa;

	}

	public static function getPessoaFisicaFromMedicoUpdateVM(MedicoUpdateViewModel $medico_update_vm): PessoaFisica {

		$pessoa_fisica = new PessoaFisica();
		if ($medico_update_vm->getCpf()) {
			$pessoa_fisica->setCpf( $medico_update_vm->getCpf() );
		}
		if ($medico_update_vm->getRg()) {
			$pessoa_fisica->setRg( $medico_update_vm->getRg() );
		}
		if ($medico_update_vm->getGenero()) {
			$pessoa_fisica->setGenero( $medico_update_vm->getGenero() );
		}
		if ($medico_update_vm->getDataNascimento()) {
			$pessoa_fisica->setDataNascimento( $medico_update_vm->getDataNascimento() );
		}
		if ($medico_update_vm->getNome()) {
			$pessoa_fisica->setNome( $medico_update_vm->getNome() );
		}
		if ($medico_update_vm->getProfissao()) {
			$pessoa_fisica->setProfissao( $medico_update_vm->getProfissao() );
		}
		if ($medico_update_vm->getEstadoCivil()) {
			$pessoa_fisica->setEstadoCivil( $medico_update_vm->getEstadoCivil() );
		}
		return $pessoa_fisica;

	}

	public static function getUsuarioFromMedicoUpdateVM(MedicoUpdateViewModel $medico_update_vm): Usuario {

		$usr = UsuarioLogado::getUsuarioId();
		$dt = DateUtils::now();
		
		$usuario = new Usuario();
		if ($medico_update_vm->getFoto()) {
			$usuario->setFoto( $medico_update_vm->getFoto() );
		}
		if ($medico_update_vm->getAtivo()) {
			$usuario->setAtivo( $medico_update_vm->getAtivo() );
		}
		if ($medico_update_vm->getAlteradoPor()) {
			$usuario->setAlteradoPor( $usr );
			$usuario->setAlteradoEm($dt);
		}
		if (strlen( trim( $medico_update_vm->getSenha() ) ) > 0) {
			$usuario->setSenha( md5($medico_update_vm->getSenha()) );
		}
		return $usuario;

	}

	public static function getMedicoFromMedicoUpdateVM(MedicoUpdateViewModel $medico_update_vm): Medico {

		$medico = new Medico();
		if ($medico_update_vm->getAssinatura()) {
			$medico->setAssinatura( $medico_update_vm->getAssinatura() );
		}
		if ($medico_update_vm->getDocumento()) {
			$medico->setDocumento( $medico_update_vm->getDocumento() );
		}
		return $medico;

	}

}