<?php

namespace App\Services;

use App\Services\Service;
use App\Services\ServiceResponse\ServiceResponse;
use App\Entities\OrcamentoCliente\OrcamentoCliente;
use Exception;
use stdClass;
use App\Mappers\OrcamentoClienteMapper;
use App\Mappers\OrcamentoClienteDetalheMapper;
use App\Services\ServiceResponse\ServiceResponseInterface;
use App\DAO\OrcamentoClienteDAO;
use App\Utils\MathUtils;
use app\ViewModels\Orcamento\OrcamentoClienteDetailViewModel\OrcamentoClienteDetailViewModel;
use App\Entities\OrcamentoClienteDetalhe\OrcamentoClienteDetalhe;
use App\ViewModels\Orcamento\OrcamentoCienteDetalheRegistrationViewModel\OrcamentoClienteDetalheRegistarionViewModel;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\DAO\DAOResponse\DAOResponse;
use App\DAO\ProcedimentoValorDAO;
use App\Utils\DateUtils;

class OrcamentoClienteService extends Service {

	public function register(array $request): ServiceResponse {

		$orcamentoCliente = '';
		$lista_orcamento_item = array ();
		$service_response = new ServiceResponse();

		try {
			$orcamentoCliente = OrcamentoClienteMapper::getOrcamentoClienteRegistrationVMFromArray( $request );
			$lista_orcamento_item = $this->setListaOrcamentoItem( $request ['itens'] );
			$this->setDadosProcedimentoValorInLista( $lista_orcamento_item );
		} catch ( Exception $e ) {
			$service_response->setStatus( ServiceResponseInterface::UNKNOWN_ERROR );
			$service_response->setErrors( $e );
			return $service_response;
		}

		$dao = new OrcamentoClienteDAO();
		$dao_orc_response = $dao->registerNewOrcamentoCliente( $orcamentoCliente );

		if ($dao_orc_response->getStatus() == DAOResponseInterface::SUCESS) {
			$resp = $dao_orc_response->getData();
			$id_orcamento = $resp ['id_orcamento'];
			$dao_orcdtl_response = $dao->registerOrcamentoClienteDetalhes( $lista_orcamento_item, $id_orcamento );
			if ($dao_orcdtl_response->getStatus() != DAOResponseInterface::SUCESS) {
				$dao_orc_response = $dao->deleteOrcamentoClienteById( $id_orcamento );
			} else {
				$dao_itens_response = $dao->getItensOrcamentoByID( $id_orcamento );
				$dao_orcamento_response = $dao->getOrcamentoByID( $id_orcamento );
				$sr_unidade = new UnidadeService();
				$sr_unidade_response = $sr_unidade->getDadosUnidadeById( $orcamentoCliente->getIdUnidade() );
				$sr_paciente = new PacienteService();
				$sr_paciente_response = $sr_paciente->getDadosPacienteByIdCiente( $orcamentoCliente->getIdCliente() );
				$sr_pet = new PetService();
				$sr_pet_response = $sr_pet->getDadosPetById( $orcamentoCliente->getIdPet() );
				$dados_unidade = $sr_unidade_response->getData();
				$dados_cliente = $sr_paciente_response->getData();
				$dados_pet = $sr_pet_response->getData();
				$ita = $dao_orcamento_response->getData();
				$itb = $dao_itens_response->getData();
				$array = [ 
					'orcamento' => $ita ['orcamento'],
					'unidade' => $dados_unidade ['unidade'],
					'cliente' => $dados_cliente,
					'pet' => $dados_pet,
					'itens' => $itb ['itens']
				];
				$dao_orcdtl_response->setData( $array );
			}
		}

		$service_response = $this->setServiceResponse( $dao_orcdtl_response );

		return $service_response;

	}

	public function update(array $request): ServiceResponse {

		$orcamentoCliente = '';
		$lista_orcamento_item = array ();
		$service_response = new ServiceResponse();

		try {
			$orcamentoCliente = OrcamentoClienteMapper::getOrcamentoClienteUpdateVMFromArray( $request );
			$lista_orcamento_item = $this->setListaOrcamentoItem( $request ['itens'] );
			$this->setDadosProcedimentoValorInLista( $lista_orcamento_item );
		} catch ( Exception $e ) {
			$service_response->setStatus( ServiceResponseInterface::UNKNOWN_ERROR );
			$service_response->setErrors( $e );
			return $service_response;
		}

		$dao = new OrcamentoClienteDAO();
		$dao_orc_response = $dao->updateOrcamentoCliente( $orcamentoCliente );

		if ($dao_orc_response->getStatus() == DAOResponseInterface::SUCESS) {
			$dao_del_response = $dao->deleteOrcamentoClienteDetalheByOcamentoId( $orcamentoCliente->getId() );
			if ($dao_del_response->getStatus() == DAOResponseInterface::SUCESS) {
				$dao_orcdtl_response = $dao->registerOrcamentoClienteDetalhes( $lista_orcamento_item, $orcamentoCliente->getId() );
				if ($dao_orcdtl_response->getStatus() == DAOResponseInterface::SUCESS) {
					$dao_itens_response = $dao->getItensOrcamentoByID( $orcamentoCliente->getId() );
					$dao_orcamento_response = $dao->getOrcamentoByID( $orcamentoCliente->getId() );
					$sr_unidade = new UnidadeService();
					$sr_unidade_response = $sr_unidade->getDadosUnidadeById( $orcamentoCliente->getIdUnidade() );
					$sr_paciente = new PacienteService();
					$sr_paciente_response = $sr_paciente->getDadosPacienteByIdCiente( $orcamentoCliente->getIdCliente() );
					$sr_pet = new PetService();
					$sr_pet_response = $sr_pet->getDadosPetById( $orcamentoCliente->getIdPet() );
					$dados_unidade = $sr_unidade_response->getData();
					$dados_cliente = $sr_paciente_response->getData();
					$dados_pet = $sr_pet_response->getData();
					$ita = $dao_orcamento_response->getData();
					$itb = $dao_itens_response->getData();
					$array = [ 
						'orcamento' => $ita ['orcamento'],
						'unidade' => $dados_unidade ['unidade'],
						'cliente' => $dados_cliente,
						'pet' => $dados_pet,
						'itens' => $itb ['itens']
					];
					$dao_orcdtl_response->setData( $array );
				}
				$service_response = $this->setServiceResponse( $dao_orcdtl_response );
			} else {
				$service_response = $this->setServiceResponse( $dao_del_response );
			}
		} else {
			$service_response = $this->setServiceResponse( $dao_orc_response );
		}

		return $service_response;

	}

	public function getListOrcamentosByClienteID(int $id_unidade, int $id_cliente): ServiceResponse {

		$service_response = new ServiceResponse();
		$dao = new OrcamentoClienteDAO();
		$dao_response = $dao->getOrcamentoByClienteIDFromUnidadeID( $id_unidade, $id_cliente );
		if ($dao_response->getStatus() == DAOResponseInterface::SUCESS) {
			$dados = $dao_response->getData();
			$list_orcamento = $dados ['orcamento'];
			$sr_pet = new PetService();
			for($i = 0; $i < count( $list_orcamento ); $i++) {
				$sr_pet_response = $sr_pet->getDadosPetById( $list_orcamento [$i] ['id_pet'] );
				$dados_pet = $sr_pet_response->getData();
				$list_orcamento [$i] ['dados_pet'] = $dados_pet;
			}
			$sr_unidade = new UnidadeService();
			$sr_unidade_response = $sr_unidade->getDadosUnidadeById( $id_unidade );
			$sr_paciente = new PacienteService();
			$sr_paciente_response = $sr_paciente->getDadosPacienteByIdCiente( $id_cliente );

			$dados_unidade = $sr_unidade_response->getData();
			$dados_cliente = $sr_paciente_response->getData();

			$array = [ 
				'orcamento' => $list_orcamento,
				'unidade' => $dados_unidade ['unidade'],
				'cliente' => $dados_cliente
			];
			$dao_response->setData( $array );
		}
		$service_response = $this->setServiceResponse( $dao_response );
		return $service_response;

	}

	public function getListOrcamentosByPetID(int $id_unidade, int $id_pet): ServiceResponse {

		$service_response = new ServiceResponse();
		$dao = new OrcamentoClienteDAO();
		$dao_response = $dao->getOrcamentoByPetIDFromUnidadeID( $id_unidade, $id_pet );
		if ($dao_response->getStatus() == DAOResponseInterface::SUCESS) {
			$dados = $dao_response->getData();
			$list_orcamento = $dados ['orcamento'];
			$id_cliente = $list_orcamento [0] ['id_cliente'];
			$sr_unidade = new UnidadeService();
			$sr_unidade_response = $sr_unidade->getDadosUnidadeById( $id_unidade );
			$sr_paciente = new PacienteService();
			$sr_paciente_response = $sr_paciente->getDadosPacienteByIdCiente( $id_cliente );
			$sr_pet = new PetService();
			$sr_pet_response = $sr_pet->getDadosPetById( $id_pet );
			$dados_unidade = $sr_unidade_response->getData();
			$dados_cliente = $sr_paciente_response->getData();
			$dados_pet = $sr_pet_response->getData();

			$array = [ 
				'orcamento' => $list_orcamento,
				'unidade' => $dados_unidade ['unidade'],
				'cliente' => $dados_cliente,
				'pet' => $dados_pet
			];
			$dao_response->setData( $array );
		}
		$service_response = $this->setServiceResponse( $dao_response );
		return $service_response;

	}

	public function getOrcamentoDetalhe(int $id_orcamento): ServiceResponse {

		$service_response = new ServiceResponse();
		$dao = new OrcamentoClienteDAO();
		$dao_response = $dao->getItensOrcamentoByID( $id_orcamento );

		$service_response = $this->setServiceResponse( $dao_response );

		return $service_response;

	}

	public function getOrcamentoId(int $id_orcamento): ServiceResponse {

		$service_response = new ServiceResponse();
		$dao_response = new DAOResponse();
		$dao = new OrcamentoClienteDAO();
		$dao_orc_response = $dao->getOrcamentoByID( $id_orcamento );
		$dao_itens_response = $dao->getItensOrcamentoByID( $id_orcamento );

		if (($dao_orc_response->getStatus() == DAOResponseInterface::SUCESS) && ($dao_itens_response->getStatus() == DAOResponseInterface::SUCESS)) {
			$dao_response->setStatus( DAOResponseInterface::SUCESS );
			$dados_orcamento = $dao_orc_response->getData();
			$dados_itens = $dao_itens_response->getData();
			$id_unidade = $dados_orcamento ['orcamento'] ['id_unidade'];
			$id_cliente = $dados_orcamento ['orcamento'] ['id_cliente'];
			$id_pet = $dados_orcamento ['orcamento'] ['id_pet'];
			$sr_unidade = new UnidadeService();
			$sr_unidade_response = $sr_unidade->getDadosUnidadeById( $id_unidade );
			$sr_paciente = new PacienteService();
			$sr_paciente_response = $sr_paciente->getDadosPacienteByIdCiente( $id_cliente );
			$sr_pet = new PetService();
			$sr_pet_response = $sr_pet->getDadosPetById( $id_pet );
			$dados_unidade = $sr_unidade_response->getData();
			$dados_cliente = $sr_paciente_response->getData();
			$dados_pet = $sr_pet_response->getData();

			$array = [ 
				'orcamento' => $dados_orcamento ['orcamento'],
				'itens' => $dados_itens ['itens'],
				'unidade' => $dados_unidade ['unidade'],
				'cliente' => $dados_cliente,
				'pet' => $dados_pet
			];
			$dao_response->setData( $array );
		} else {
			$dao_response->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
		}

		$service_response = $this->setServiceResponse( $dao_response );

		return $service_response;

	}

	public function registerRequisicaoFromOrcamento(array $request): ServiceResponse {

		$orcamentoCliente = '';
		$lista_orcamento_item = array ();
		$service_response = new ServiceResponse();

		try {
			$orcamentoCliente = OrcamentoClienteMapper::getOrcamentoClienteUpdateVMFromArray( $request );
			$lista_orcamento_item = $this->setListaOrcamentoItemToRequisicao( $request ['itens'] );
			$this->setDadosProcedimentoValorInLista( $lista_orcamento_item );
			$dados = array ();
			$status = ServiceResponseInterface::SUCESS;
			for($i = 0; $i < count( $lista_orcamento_item ); $i++) {
				$requisicao_service = new RequisicaoService();
				$item = OrcamentoClienteDetalheMapper::initOrcamentoClienteItemDetalhe();
				$item = $lista_orcamento_item [$i];
				if (($item->getIdTipoProcedimento() == 4) || ($item->getIdTipoProcedimento() == 5)) {
					$req_response = $requisicao_service->registerRequisicaoExameFromOrcamento( $item );
					if ($req_response->getStatus() != ServiceResponseInterface::SUCESS) {
						$status = $req_response;
						$arr = OrcamentoClienteDetalheMapper::OrcamentoClienteItemDetalheToArray( $req_response->getData() ['item'] );
						array_push( $dados, $arr );
					} else {
						$arr = OrcamentoClienteDetalheMapper::OrcamentoClienteItemDetalheToArray( $req_response->getData() ['item'] );
						array_push( $dados, $arr );
					}
				}

				if (($item->getIdTipoProcedimento() == 2) || ($item->getIdTipoProcedimento() == 3) || ($item->getIdTipoProcedimento() == 6)) {
					$req_response = $requisicao_service->registerRequisicaoConsultaFromOrcamento( $item );
					if ($req_response->getStatus() != ServiceResponseInterface::SUCESS) {
						$status = $req_response;
						$arr = OrcamentoClienteDetalheMapper::OrcamentoClienteItemDetalheToArray( $req_response->getData() ['item'] );
						array_push( $dados, $arr );
					} else {
						$arr = OrcamentoClienteDetalheMapper::OrcamentoClienteItemDetalheToArray( $req_response->getData() ['item'] );
						array_push( $dados, $arr );
					}
				}
			}

			$service_response->setStatus( $status );

			$exec_orcabemto_response = $this->setOrcamentoToExecutado( $orcamentoCliente->getId() );

			if ($exec_orcabemto_response->getStatus() == ServiceResponseInterface::SUCESS) {
				$resp_orc_exec = [ 
					"res_orc" => [ 
						'orcamento_id' => $orcamentoCliente->getId(),
						'status_id' => 2,
						'desc' => 'executado'
					]
				];
				array_push( $dados, $resp_orc_exec );
			}

			$service_response->setData( $dados );
		} catch ( Exception $e ) {
			$service_response->setStatus( ServiceResponseInterface::UNKNOWN_ERROR );
			$service_response->setErrors( $e );
			return $service_response;
		}

		return $service_response;

	}

	public function setOrcamentoToExecutado(int $id_orcamento): ServiceResponse {

		$service_response = new ServiceResponse();
		$dao = new OrcamentoClienteDAO();
		$daoResponse = $dao->setOrcamentoToExecutado( $id_orcamento );

		$service_response = $this->setServiceResponse( $daoResponse );

		return $service_response;

	}

	public function getOrcamentoByClienteIdFromUnidadeFromStatusId(int $id_cliente, int $id_unidade, int $id_status): ServiceResponse {

		$service_response = new ServiceResponse();
		$dao = new OrcamentoClienteDAO();

		return $service_response;

	}

	public function getOrcamentoByClienteIdFromUnidadeFromPeriodo(int $id_cliente, int $id_unidade, int $id_status, int $data_inicio, int $data_fim): ServiceResponse {

		$service_response = new ServiceResponse();
		$dao = new OrcamentoClienteDAO();

		return $service_response;

	}

	private function setListaOrcamentoItem(array $itens): array {

		$lista_resp = array ();
		for($i = 0; $i < count( $itens ); $i++) {
			$item = $itens [$i];
			$obj = OrcamentoClienteDetalheMapper::getOrcamentoClienteDetalheRegistrationVMFromArray( $item );
			$obj->setValor( MathUtils::getDecimalFormatFromFloat( floatval( $obj->getValorUnidade() ) * $obj->getQuantidade() ) );
			$obj->setValorUnidade( MathUtils::getDecimalFormatFromFloat( floatval( $obj->getValorUnidade() ) ) );

			array_push( $lista_resp, $obj );
		}
		return $lista_resp;

	}

	private function setListaOrcamentoItemToRequisicao(array $itens): array {

		$lista_resp = array ();
		for($i = 0; $i < count( $itens ); $i++) {
			$item = $itens [$i] ['id'];
			$daoItem = new OrcamentoClienteDAO();
			$itemResponse = $daoItem->getOrcamentoItemById( $item );
			if ($itemResponse->getStatus() != DAOResponseInterface::SUCESS) {
			} else {
				$resposta = $itemResponse->getData();
				$detalhe = OrcamentoClienteDetalheMapper::getOrcamentoClienteDetalheToRequisicaoVM( $resposta ['item'] );
				array_push( $lista_resp, $detalhe );
			}
		}
		return $lista_resp;

	}

	private function setDadosProcedimentoValorInLista(array $lista): bool {

		$service = new ProcedimentoValorService();
		try {
			for($i = 0; $i < count( $lista ); $i++) {
				$item = $lista [$i];
				$id_procedimento_valor = intval( $item->getIdProcedimentoValor() );
				$service_response = $service->getDadosProcedimentoValorByID( $id_procedimento_valor );
				if ($service_response->getStatus() == ServiceResponseInterface::SUCESS) {
					$dados = $service_response->getData();
					$item->setIdProcedimento( intval( $dados ['id_procedimento'] ) );
					$item->setProcedimento( $dados ['procedimento'] );
					$item->setIdTipoProcedimento( intval( $dados ['id_tipo_procedimento'] ) );
					$item->setTipoProcedimento( $dados ['tipo_procedimento'] );
					$item->setIdConvenioProcedimento( intval( $dados ['id_convenio_procedimento'] ) );
					$item->setIdTipoConvenio( intval( $dados ['id_tipo_convenio'] ) );
					$item->setTipoConvenio( $dados ['tipo_convenio'] );
					$item->setIdConvenio( intval( $dados ['id_convenio'] ) );
					$item->setCodConvenio( $dados ['cod_convenio'] );
					$item->setIdUnidade( intval( $dados ['id_unidade'] ) );
					$item->setStatusProcedimentoValor( intval( $dados ['status_procedimento_valor'] ) );

					$lista [$i] = $item;
				}
			}
			return true;
		} catch ( Exception $e ) {
			log_message( "ERROR:", $e->getCode() );
			log_message( "ERROR:", $e->getMessage() );
			log_message( "ERROR:", $e->getTrace() );
			return false;
		}

	}

	private function setDetalhesProcedimentoValorInLista(array $lista): bool {

		$service = new ProcedimentoValorService();
		try {
			for($i = 0; $i < count( $lista ); $i++) {
				$item = $lista [$i];
				$id_procedimento_valor = intval( $item->getIdProcedimentoValor() );
				$service_response = $service->getDetalhesProcedimentoValorByID( $id_procedimento_valor );
				if ($service_response->getStatus() == ServiceResponseInterface::SUCESS) {
					$dados = $service_response->getData();
					$item->setIdProcedimento( intval( $dados ['id_procedimento'] ) );
					$item->setIdConvenioProcedimento( intval( $dados ['id_convenio_procedimento'] ) );
					$lista [$i] = $item;
				}
			}
			return true;
		} catch ( Exception $e ) {
			log_message( "ERROR:", $e->getCode() );
			log_message( "ERROR:", $e->getMessage() );
			log_message( "ERROR:", $e->getTrace() );
			return false;
		}

	}

	public function isValidOrcamento(array $request): bool {

		$orcamentoCliente = OrcamentoClienteMapper::getOrcamentoClienteUpdateVMFromArray( $request );
		$dao = new OrcamentoClienteDAO();
		$dao_esponse = $dao->getDadosValidarOrcamento( $orcamentoCliente->getId() );

		if ($dao_esponse->getStatus() != DAOResponseInterface::SUCESS) {
			return false;
		}

		$resp = $dao_esponse->getData();
		$validade = $resp ['orcamento'] ['validade'];
		$dt_cr = $resp ['orcamento'] ['data_criacao'];
		$dataLimite = DateUtils::addDayToDate( intval( $validade ), $dt_cr );
		$hoje = DateUtils::today();
		if ($dataLimite < $hoje) {
			return false;
		}

		return true;

	}
	
	public function isValidOrcamentoUnidade(array $request): bool {
		
		$orcamentoCliente = OrcamentoClienteMapper::getOrcamentoClienteUpdateVMFromArray( $request );
		$dao = new OrcamentoClienteDAO();
		$dao_esponse = $dao->getDadosValidarOrcamentoUnidade( $orcamentoCliente->getId(), $orcamentoCliente->getIdUnidade() );
		
		if ($dao_esponse->getStatus() != DAOResponseInterface::SUCESS) {
			return false;
		}
		
		$resp = $dao_esponse->getData();
		$validade = $resp ['orcamento'] ['validade'];
		$dt_cr = $resp ['orcamento'] ['data_criacao'];
		$dataLimite = DateUtils::addDayToDate( intval( $validade ), $dt_cr );
		$hoje = DateUtils::today();
		if ($dataLimite < $hoje) {
			return false;
		}
		
		return true;
		
	}

	public function syncOrcamentoStatusExpirado(int $id_orcamento): ServiceResponse {

		$service_response = new ServiceResponse();
		$dao = new OrcamentoClienteDAO();
		$daoResponse = $dao->syncOrcamentoStatusExpirado( $id_orcamento );

		$service_response = $this->setServiceResponse( $daoResponse );

		return $service_response;

	}

	public function syncOrcamentoStatusExpiradoUnidadeCliente(int $id_unidade,int $id_cliente): ServiceResponse {
		
		$service_response = new ServiceResponse();
		$dao = new OrcamentoClienteDAO();
		$daoResponse = $dao->syncOrcamentoStatusExpiradoUnidadeCliente($id_unidade,$id_cliente );
		
		$service_response = $this->setServiceResponse( $daoResponse );
		
		return $service_response;
		
	}
	
	public function syncOrcamentoStatusExpiradoUnidadePet(int $id_unidade,int $id_pet): ServiceResponse {
		
		$service_response = new ServiceResponse();
		$dao = new OrcamentoClienteDAO();
		$daoResponse = $dao->syncOrcamentoStatusExpiradoUnidadePet($id_unidade,$id_pet );
		
		$service_response = $this->setServiceResponse( $daoResponse );
		
		return $service_response;
		
	}
}

