<?php

namespace App\Services;

use App\DAO\AgendamentoVoucherDAO;
use App\DAO\LojaCompraDAO;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\Entities\PagSeguro\Order\PagSeguroCharges;
use App\Entities\PagSeguro\Order\PagSeguroCustomer;
use App\Entities\PagSeguro\Order\PagSeguroOrder;
use App\Entities\PagSeguro\Order\PagSeguroPaymentMethod;
use App\Entities\PagSeguro\Share\PagSeguroAddress;
use App\Mappers\PagSeguroMapper;
use App\Services\ServiceResponse\ServiceResponse;
use App\Services\ServiceResponse\ServiceResponseInterface;
use App\ViewModels\LojaCompra\LojaCompraCartaoCreditoPagSeguro\LojaCompraRegistrationViewModel\LojaCompraProdutoRegistrationViewModel;
use App\Mappers\LojaCompraMapper;
use Exception;

class LojaCompraService extends Service {

	public function registerCompraCartaoPagseguro(array $dados): ServiceResponse {

		$serviceReponse = new ServiceResponse();
		$pagSeguro_service = new PagSeguroService();
		$lojacompraitem_service = new LojaCompraItemsService();
		$serial_service = new SerialSevice();
		$usuario_service = new UsuarioService();
		$voucher_service = new VoucherService();
		$lojacompra_dao = new LojaCompraDAO();

		$serial_response = $serial_service->getNewSerialUUID();
		if ($serial_response->getStatus() != ServiceResponseInterface::SUCESS) {
			$serviceReponse = $this->setServiceResponse( $serial_response );
			return $serviceReponse;
		}

		$serial_resp = $serial_response->getData() ['seria_uuid'];
		$usuario_response = $usuario_service->getDadosUsuarioByIdTolojacompra( $dados ['id_usuario'] );

		if ($usuario_response->getStatus() != ServiceResponseInterface::SUCESS) {
			$serviceReponse = $this->setServiceResponse( $serial_response );
			return $serviceReponse;
		}

		$usuario_resp = $usuario_response->getData() [0];

		// $produtos = LojaCompraMapper::getLojaCompraProdutosRegistrationViewModelFromArray( $dados );

		try {
			$lojaCompra_regist = LojaCompraMapper::getLojaCompracartaoCreditoRegistrationViewModelFromArray( $dados );
			$produtos = $this->setNomeInProdutos( LojaCompraMapper::getLojaCompraProdutosRegistrationViewModelFromArray( $dados ) );
			$card = LojaCompraMapper::getLojaCompraCardRegistrationViewModelFromArray( $dados );
			$payment = LojaCompraMapper::getLojaCompraPayamentMethodRegistrationViewModelFromArray( $dados, $card );
			$compra = LojaCompraMapper::getLojaCompraCartaoRegistrationViewModelFromArray( $dados, $produtos, $payment );

			$pagSeguroPhone = PagSeguroMapper::getPagSeguroPhoneFromDadosCompra( $usuario_resp );
			$pagSeguroCustomer = PagSeguroMapper::getPagSeguroCustomerFromDadosCompra( $usuario_resp, $pagSeguroPhone );
			$pagSeguroItems = PagSeguroMapper::getPagSeguroItemsArrayFromProdutos( $produtos );
			$pagSeguroShipping = PagSeguroMapper::getPagSeguroShippingFromDadosCompra( PagSeguroMapper::getPagSeguroAddressFromDadosCompra( $usuario_resp ) );
			$pagSeguroNotificationUrls = getenv( 'pgs.notification' );
			$pagSeguroHolder = PagSeguroMapper::getPagSeguroHolderFromDadosCard( $card );
			$pagSeguroCard = PagSeguroMapper::getPagSeguroCardfromDadoscompra( $card, $pagSeguroHolder );
			$pagSeguroPaymentMethod = PagSeguroMapper::getPagSeguroPaymentMethodfromDadosCompra( $payment, $pagSeguroCard );
			$amount = PagSeguroMapper::getPagSeguroAmountFromDadosCompra( $compra );
			$charges = [ 
				PagSeguroMapper::getPagSeguroChargesFromDadosCompra( $serial_resp, $amount, $pagSeguroPaymentMethod ),
				$pagSeguroPaymentMethod
			];

			$pagSeguroOrder = PagSeguroMapper::getPagSeguroOrderFromDTOS( $serial_resp, $pagSeguroCustomer, $pagSeguroItems, $pagSeguroShipping, $charges );

			$pg_text = $this->getArrayPagSeguro( $pagSeguroOrder, $pagSeguroCustomer, $pagSeguroPaymentMethod, $pagSeguroShipping->getAddress(), $pagSeguroItems,
				$charges [0] );

			$response_createcompra = $lojacompra_dao->registerCompra( $lojaCompra_regist );

			$json = json_encode( $pg_text, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );

			if ($response_createcompra->getStatus() != DAOResponseInterface::SUCESS) {
				$serviceReponse = $this->setServiceResponse( $response_createcompra );
				return $serviceReponse;
			}

			$resp_loja_compra = $response_createcompra->getData() ['id_compra'];

			$response_compra_item = $lojacompraitem_service->registerItensCompra( $resp_loja_compra, $dados ['id_usuario'], $produtos );

			if ($response_compra_item->getStatus() != ServiceResponseInterface::SUCESS) {
				$response_exculir_item = $lojacompraitem_service->excluirItemsByCompraId( $resp_loja_compra );
				$response_exculir_compra = $lojacompra_dao->excluirCompraById( $resp_loja_compra );
				return $response_compra_item;
			}

			$response_pg_request_regist = $pagSeguro_service->registerRequest( $json, getenv( 'pgs.send.orders' ), $serial_resp, intval( $resp_loja_compra ) );

			$lojacompra_dao->changeStatusCompra($resp_loja_compra, 2);
			
			$response_send_pagseguro = $pagSeguro_service->sendRequestCartaoCredito( $json );
			if ($response_send_pagseguro->getStatus() == ServiceResponseInterface::SUCESS) {
				
				$resp_pagseguro = $response_send_pagseguro->getData();
				$resposta_status = $resp_pagseguro ['obj_resposta'] ['status_compra'];
				
				$response_compra_status = ServiceResponseInterface::INSUFFICIENT_DATA;				
				$voucher_response == ServiceResponseInterface::INSUFFICIENT_DATA;
				
				switch (strtoupper( $resposta_status )) {
					case 'AUTHORIZED' :
						$response_compra_status = $lojacompra_dao->changeStatusCompra( $resp_loja_compra, 4 );
						$voucher_response = $voucher_service->registerVoucher( $dados, $resp_loja_compra );
						$serviceReponse = $this->setServiceResponse( $response_createcompra );
						break;
					case 'IN_ANALYSIS' :
						$response_compra_status = $lojacompra_dao->changeStatusCompra( $resp_loja_compra, 4 );
						$voucher_response = $voucher_service->registerVoucher( $dados, $resp_loja_compra );
						$serviceReponse = $this->setServiceResponse( $response_createcompra );
						break;
					case 'PAID' :
						$response_compra_status = $lojacompra_dao->changeStatusCompra( $resp_loja_compra, 3 );
						$voucher_response = $voucher_service->registerVoucher( $dados, $resp_loja_compra );
						$serviceReponse = $this->setServiceResponse( $response_createcompra );
						break;
					case 'DECLINED' :
						$response_compra_status = $lojacompra_dao->changeStatusCompra( $resp_loja_compra, 5 );
						$serviceReponse = $this->setServiceResponse( $response_createcompra );
						$serviceReponse->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
						break;
					case 'CANCELED' :
						$response_compra_status = $lojacompra_dao->changeStatusCompra( $resp_loja_compra, 5 );
						$serviceReponse = $this->setServiceResponse( $response_createcompra );
						$serviceReponse->setStatus( ServiceResponseInterface::VALIDATION_PARAMS_ERROR );
						break;
					default :
						$response_compra_status = $lojacompra_dao->changeStatusCompra( $resp_loja_compra, 4 );
						$voucher_response = $voucher_service->registerVoucher( $dados, $resp_loja_compra );
						$serviceReponse = $this->setServiceResponse( $response_createcompra );
						break;
				}

				
				// $serviceReponse = $this->setServiceResponse( $response_createcompra );
				if ($voucher_response == ServiceResponseInterface::SUCESS) {
					$serviceReponse->setData( [ 
						$response_createcompra->getData(),
						$voucher_response->getData()
					] );
				}
				//$serviceReponse->setStatus( ServiceResponseInterface::SUCESS );
			}
		} catch ( Exception $e ) {
			$serviceReponse->setErrors( [ 
				'code' => $e->getCode(),
				'message' => $e->getMessage()
			] );
			switch ($e->getCode()) {
				case 400 :
					$serviceReponse->setStatus( ServiceResponseInterface::INSUFFICIENT_DATA );
					break;

				case 401 :
					$serviceReponse->setStatus( ServiceResponseInterface::UNAUTHORIZED );
					break;

				case 403 :
					$serviceReponse->setStatus( ServiceResponseInterface::FORBIDDEN );
					break;

				default :
					$serviceReponse->setStatus( ServiceResponseInterface::UNKNOWN_ERROR );
					break;
			}
		}

		return $serviceReponse;

	}

	private function getArrayPagSeguro(PagSeguroOrder $pagseguooreder, PagSeguroCustomer $customer, PagSeguroPaymentMethod $payment, PagSeguroAddress $address,
			array $items, PagSeguroCharges $charges): array {

		$order = array ();

		$it = array ();
		foreach ( $items as $produto ) {
			$p = [ 
				'reference_id' => $produto->getReferenceId(),
				'name' => $produto->getName(),
				'quantity' => $produto->getQuantity(),
				'unit_amount' => $produto->getUnitAmount()
			];
			array_push( $it, $p );
		}

		$order = [ 
			'reference_id' => $pagseguooreder->getReferenceId(),
			'customer' => [ 
				'name' => $customer->getNome(),
				'email' => $customer->getEmail(),
				'tax_id' => $customer->getTaxId(),
				'phones' => [ 
					[ 
						'country' => intval( $customer->getPhone()
							->getCountry() ),
						'area' => intval( $customer->getPhone()
							->getArea() ),
						'number' => intval( $customer->getPhone()
							->getNumber() ),
						'type' => $customer->getPhone()
							->getType()
					]
				]
			],
			'items' => $it,
			'shipping' => [ 
				'address' => [ 
					'street' => $address->getStreet(),
					'number' => $address->getNumber(),
					'complement' => "...",
					'locality' => $address->getLocality(),
					'city' => $address->getCity(),
					'region_code' => $address->getRegionCode(),
					'country' => $address->getCountry(),
					'postal_code' => $address->getPostalCode()
				]
			],
			'notification_urls' => [ 
				getenv( 'pgs.notification' )
			],
			'charges' => [ 
				[ 
					'reference_id' => $charges->getRefernceId(),
					'description' => $charges->getDescription(),
					'amount' => [ 
						'value' => $charges->getAmount()
							->getValue(),
						'currency' => $charges->getAmount()
							->getCurrency()
					],
					'payment_method' => [ 
						'type' => $payment->getType(),
						'installments' => $payment->getInstallments(),
						'capture' => $payment->getCapture(),
						'soft_descriptor' => $payment->getSoftDescriptor(),
						'card' => [ 
							'encrypted' => $payment->getCard()
								->getEncrypted(),
							'exp_month' => $payment->getCard()
								->getExpMonth(),
							'exp_year' => $payment->getCard()
								->getExpYear(),
							'security_code' => $payment->getCard()
								->getSecurityCode(),
							'holder' => [ 
								'name' => $payment->getCard()
									->getHolder()
									->getName()
							],
							'store' => false
						]
					]
				]
			]
		];

		return $order;

	}

	public function registerCompraPixPagseguro(array $dados): ServiceResponse {

		$serviceReponse = new ServiceResponse();
		$pagSeguro_service = new PagSeguroService();

		return $serviceReponse;

	}

	public function getComprasByLojaId(int $id_loja, int $id_status_compra): ServiceResponse {

		$serviceReponse = new ServiceResponse();

		$produtoDao = new LojaCompraDAO();
		$daoResponse = $produtoDao->getComprasByLojaId( $id_loja, $id_status_compra );
		$serviceReponse = $this->setServiceResponse( $daoResponse );

		return $serviceReponse;

	}

	public function getPetsByComprasId(array $compras_id): ServiceResponse {

		$serviceReponse = new ServiceResponse();

		$produtoDao = new LojaCompraDAO();
		$daoResponse = $produtoDao->getPetsByComprasId( $compras_id );
		$serviceReponse = $this->setServiceResponse( $daoResponse );

		return $serviceReponse;

	}

	public function getIdsCompras(array $compras): array {

		$array_ids = array ();

		for($i = 0; $i < count( $compras ); $i++) {
			$id = $compras [$i] ['id'];
			array_push( $array_ids, $id );
		}

		return $array_ids;

	}

	public function getIdsComprasFromLojaCompraItem(array $compras): array {

		$array_ids = array ();

		for($i = 0; $i < count( $compras ); $i++) {
			$id = $compras [$i] ['id_loja_compra'];
			array_push( $array_ids, $id );
		}

		return $array_ids;

	}

	public function getComprasItensById(int $id_loja_compra): ServiceResponse {

		$serviceReponse = new ServiceResponse();

		$produtoDao = new LojaCompraDAO();
		$daoResponse = $produtoDao->getComprasItensById( $id_loja_compra );
		$serviceReponse = $this->setServiceResponse( $daoResponse );

		return $serviceReponse;

	}

	private function setNomeInProdutos(array $produtos): array {

		$lojaProduto_service = new LojaProdutoService();

		$result = array ();

		for($i = 0; $i < count( $produtos ); $i++) {
			$produto = new LojaCompraProdutoRegistrationViewModel();
			$produto = $produtos [$i];
			$response = $lojaProduto_service->getNomeProdutoByLojaProdutoId( $produto->getIdLojaProduto() );
			if ($response->getStatus() == DAOResponseInterface::SUCESS) {
				$dados = $response->getData();
				$produto->setNome( $dados ['nome'] );
				array_push( $result, $produto );
			} else {
				throw new Exception( "Produto sem nome" );
			}
		}
		return $result;

	}

	public function registerCompraMedicinaCarinho(array $dados): ServiceResponse {

		$serviceReponse = new ServiceResponse();
		$lojacompraitem_service = new LojaCompraItemsService();
		$voucher_service = new VoucherService();
		$lojacompra_dao = new LojaCompraDAO();
		$agendamento_voucher_dao = new AgendamentoVoucherDAO();

		try {
			$lojaCompra_regist = LojaCompraMapper::getLojaCompraMedicinaCarinhoViewModelFromArray( $dados );
			$response_createcompra = $lojacompra_dao->registerCompraMedicinaCarinho( $lojaCompra_regist );
			if ($response_createcompra->getStatus() != DAOResponseInterface::SUCESS) {
				$serviceReponse = $this->setServiceResponse( $response_createcompra );
				return $serviceReponse;
			}
			$resp_loja_compra = $response_createcompra->getData() ['id_compra'];

			$response_loja_porduto_id = $lojacompra_dao->getProdutoLojaId();
			if ($response_loja_porduto_id->getStatus() != DAOResponseInterface::SUCESS) {
				$serviceReponse = $this->setServiceResponse( $response_loja_porduto_id );
				return $serviceReponse;
			}
			$resp_loja_porduto_id = $response_loja_porduto_id->getData() ['id_tipo_produto'];

			$dados ['produtos'] [0] ['id_loja_produto'] = $resp_loja_porduto_id ['id_loja_produto'];
			$dados ['produtos'] [0] ['nome'] = 'MCCVET100';
			$dados ['produtos'] [0] ['quantidade'] = 1;
			$dados ['produtos'] [0] ['valor_unidade'] = 0;
			$dados ['produtos'] [0] ['valor'] = 0;

			$produtos = $this->setNomeInProdutos( LojaCompraMapper::getLojaCompraProdutosRegistrationViewModelFromArray( $dados ) );
			$response_compra_item = $lojacompraitem_service->registerItensCompra( $resp_loja_compra, $dados ['id_usuario'], $produtos );

			if ($response_compra_item->getStatus() != ServiceResponseInterface::SUCESS) {
				$response_exculir_item = $lojacompraitem_service->excluirItemsByCompraId( $resp_loja_compra );
				$response_exculir_compra = $lojacompra_dao->excluirCompraById( $resp_loja_compra );
				return $response_compra_item;
			}

			$response_compra_status = $lojacompra_dao->changeStatusCompra( $resp_loja_compra, 3 );

			$voucher_response = $voucher_service->registerVoucher( $dados, $resp_loja_compra );
			$serviceReponse = $this->setServiceResponse( $response_createcompra );
			if ($voucher_response == ServiceResponseInterface::SUCESS) {
				$serviceReponse->setData( [ 
					$response_createcompra->getData(),
					$voucher_response->getData()
				] );
			}

			$response_agendamento = $agendamento_voucher_dao->register( $dados ['id_agendamento'], $voucher_response->getData() ['vouchers'] [0] ['id_voucher'] );
			if ($response_agendamento->getStatus() != DAOResponseInterface::SUCESS) {
				$serviceReponse = $this->setServiceResponse( $response_agendamento );
				return $serviceReponse;
			}

			// $serviceReponse->setStatus( ServiceResponseInterface::SUCESS );
		} catch ( Exception $e ) {
			$serviceReponse->setErrors( [ 
				'code' => $e->getCode(),
				'message' => $e->getMessage()
			] );
			$serviceReponse->setStatus( ServiceResponseInterface::UNKNOWN_ERROR );
		}
		$serviceReponse->setStatus( ServiceResponseInterface::SUCESS );

		return $serviceReponse;

	}

}

