<?php

namespace App\Services;

use App\Services\Service;
use App\Services\ServiceResponse\ServiceResponse;
use App\DAO\PagSeguroRequestDAO;
use App\DAO\PagSeguroResponseDAO;
use GuzzleHttp\Client;
use Config\Services;
use App\Services\ServiceResponse\ServiceResponseInterface;
use App\ViewModels\PagSeguro\PagSeguroResponseViewModel\PagSeguroChargeViewModel;
use App\ViewModels\PagSeguro\PagSeguroResponseViewModel\PagSeguroCustomerViewModel;
use App\ViewModels\PagSeguro\PagSeguroResponseViewModel\PagSeguroPhonesViewModel;
use function GuzzleHttp\json_decode;
use App\Mappers\PagSeguroResponseMapper;
use App\Mappers\PagSeguroWebHookNotificationCredCardMapper;
use App\DAO\PagSeguroNotificationDAO;
use App\ViewModels\PagSeguro\PagSeguroNotificationCreditCard\PagSeguroChargeViewModel as NotificationPagSeguroChargeViewModel;
use App\ViewModels\PagSeguro\PagSeguroNotificationCreditCard\PagSeguroCustomerViewModel as NotificationPagSeguroCustomerViewModel;
use App\DAO\LojaCompraDAO;
use App\DAO\DAOResponse\DAOResponseInterface;

class PagSeguroService extends Service {

	public function registerRequest(string $objrequest, string $url, string $referenceid, int $idlojacompra): ServiceResponse {

		$dao = new PagSeguroRequestDAO();
		$service_response = new ServiceResponse();
		$daoResponse = $dao->registerRequest( $objrequest, $url, $referenceid, $idlojacompra );
		$service_response = $this->setServiceResponse( $daoResponse );

		return $service_response;

	}

	public function registerResponse(string $objresponse, string $referenceid, string $orderid, PagSeguroChargeViewModel $charge,
			PagSeguroCustomerViewModel $customer): ServiceResponse {

		$dao = new PagSeguroResponseDAO();
		$service_response = new ServiceResponse();
		$daoResponse = $dao->registerResponse( $objresponse, $referenceid, $orderid, $charge, $customer );
		$service_response = $this->setServiceResponse( $daoResponse );

		return $service_response;

	}

	private function persistNotification($dados, string $referenceid, string $notificationid, NotificationPagSeguroChargeViewModel $charge,
			NotificationPagSeguroCustomerViewModel $customer): ServiceResponse {

		$json = json_encode( $dados, JSON_UNESCAPED_UNICODE );
		$dao = new PagSeguroNotificationDAO();
		$service_response = new ServiceResponse();
		$daoResponse = $dao->registerNotification( $json, $referenceid, $notificationid, $charge, $customer );
		$service_response = $this->setServiceResponse( $daoResponse );
		return $service_response;

	}

	private function changeStatusCompra(string $referenceid, string $change_status): ServiceResponse {

		$service_response = new ServiceResponse();
		$lojacompra_dao = new LojaCompraDAO();

		$compra_response = $lojacompra_dao->getCompraIdByReferenceId( $referenceid );

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

		$idcompra = $compra_response->getData() ['compra'] ['id'];

		switch (strtoupper( $change_status )) {
			case 'AUTHORIZED' :
				$response_compra_status = $lojacompra_dao->changeStatusCompra( $idcompra, 4 );
				$service_response = $this->setServiceResponse( $response_compra_status );
				break;
			case 'IN_ANALYSIS' :
				$response_compra_status = $lojacompra_dao->changeStatusCompra( $idcompra, 4 );
				$service_response = $this->setServiceResponse( $response_compra_status );
				break;
			case 'PAID' :
				$response_compra_status = $lojacompra_dao->changeStatusCompra( $idcompra, 3 );
				$service_response = $this->setServiceResponse( $response_compra_status );
				break;
			case 'DECLINED' :
				$response_compra_status = $lojacompra_dao->changeStatusCompra( $idcompra, 5 );
				$service_response = $this->setServiceResponse( $response_compra_status );
				break;
			case 'CANCELED' :
				$response_compra_status = $lojacompra_dao->changeStatusCompra( $idcompra, 5 );
				$service_response = $this->setServiceResponse( $response_compra_status );
				break;
		}

		return $service_response;

	}

	public function registerNotification(array $dados): ServiceResponse {

		$service_response = new ServiceResponse();
		$pagseguroNotification = PagSeguroWebHookNotificationCredCardMapper::getPagSeguroNotificationFromObj( $dados );

		$charges = $pagseguroNotification->getCharges()
			->getCharges();
		$customer = $pagseguroNotification->getCustomer();
		$obj_resposta = array ();
		for($i = 0; $i < count( $charges ); $i++) {
			$charge = $charges [$i];
			$notificationRegister = $this->persistNotification( $dados, $pagseguroNotification->getReferenceId(), $pagseguroNotification->getId(), $charge,
				$customer );
			if ($notificationRegister->getStatus() == ServiceResponseInterface::SUCESS) {
				$resp = $this->changeStatusCompra( $pagseguroNotification->getReferenceId(), $charge->getStatus() );
				$obj_resposta = [ 
					'status_compra' => $charge->getStatus(),
					$notificationRegister->getData()
				];
				$service_response->setStatus( $notificationRegister->getStatus() );
			}
		}
		$service_response->setData( [ ] );
		$service_response->setStatus( ServiceResponseInterface::SUCESS );
		// $service_response = $this->setServiceResponse( $daoResponse );
		return $service_response;

	}

	public function getKey(): ServiceResponse {

		$service_response = new ServiceResponse();

		$client = new Client();

		$token = 'Bearer ' . getenv( 'pgs.token' );

		$response = $client->request( 'GET', getenv( 'pgs.keypub' ), [ 
			'headers' => [ 
				'Authorization' => $token,
				'accept' => 'application/json'
			]
		] );

		if (intval( $response->getStatusCode() ) == 200) {

			$service_response->setData( json_decode( $response->getBody() ) );
			$service_response->setStatus( ServiceResponseInterface::SUCESS );
		} else {
			$service_response->setStatus( ServiceResponseInterface::UNKNOWN_ERROR );
		}
		return $service_response;

	}

	public function sendRequestCartaoCredito(string $objrequest): ServiceResponse {

		$service_response = new ServiceResponse();

		$client = new Client();

		$token = 'Bearer ' . getenv( 'pgs.token' );

		$response = $client->request( 'POST', getenv( 'pgs.send.orders' ),
			[ 
				'headers' => [ 
					'Authorization' => $token,
					'accept' => 'application/json'
				],
				'body' => $objrequest
			] );

		if ((intval( $response->getStatusCode() ) == 200 || intval( $response->getStatusCode() ) == 201)) {
			// $pgs_service = new PagSeguroResponseService();
			$pgsresponse = json_decode( $response->getBody() );

			$pagseguroResponse = PagSeguroResponseMapper::getPagSeguroResponseFromObj( $pgsresponse );

			$charges = $pagseguroResponse->getCharges()
				->getCharges();
			$customer = $pagseguroResponse->getCustomer();
			$obj_resposta = array ();
			for($i = 0; $i < count( $charges ); $i++) {
				$charge = $charges [$i];
				$responseRegister = $this->registerResponse( $response->getBody(), $pagseguroResponse->getReferenceId(), $pagseguroResponse->getId(), $charge,
					$customer );
				if ($responseRegister->getStatus() == ServiceResponseInterface::SUCESS) {
					$obj_resposta = [ 
						'status_compra' => $charge->getStatus(),
						$responseRegister->getData()
					];
					$service_response->setStatus( $responseRegister->getStatus() );
				}
			}
			$service_response->setData( [ 
				'pgs_response' => $pgsresponse,
				'obj_resposta' => $obj_resposta
			] );
			$service_response->setStatus( ServiceResponseInterface::SUCESS );
		} else {
			$service_response->setStatus( ServiceResponseInterface::INSUFFICIENT_DATA );
			$service_response->setErrors( json_decode( $response->getBody() ) );
			$service_response->setData( json_decode( $response->getBody() ) );
		}
		return $service_response;

	}

	public function getPagSeguroPhonesFromResponse(array $response): PagSeguroPhonesViewModel {

		$dados = $response ['customer'] ['phones'];

		$result = PagSeguroResponseMapper::getPagSeguroResponsePhonesFromArray( $dados );

		return $result;

	}

}

