<?php

namespace apexl\Io\modules\paymentDisplay\controllers;

use apexl\Config\Singleton;
use apexl\Io\includes\Controller;
use apexl\Io\includes\Hook;
use apexl\Io\includes\Routes;
use apexl\Io\includes\System;
use apexl\Io\modules\display\components\BasicLink;
use apexl\Io\modules\display\components\ColWrapper;
use apexl\Io\modules\display\components\ContentTitle;
use apexl\Io\modules\display\components\EntityDisplayTile;
use apexl\Io\modules\display\components\FormComponent;
use apexl\Io\modules\display\components\Iframe;
use apexl\Io\modules\display\components\RowWrapper;
use apexl\Io\modules\display\components\SimpleButton;
use apexl\Io\modules\display\services\Render;
use apexl\Io\modules\invoice\entities\invoiceEntity;
use apexl\Io\modules\payment\entities\paymentEntity;
use apexl\Io\modules\payment\services\paymentService;
use apexl\Io\modules\paymentDisplay\components\viewTiles;
use apexl\Io\modules\subscription\entities\subscriptionEntity;
use apexl\Io\modules\user\entities\userEntity;
use apexl\Io\services\Logger;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

class paymentController extends Controller {
    protected $render;

    public function __construct(Render $render)
    {
        parent::__construct();
        $this->render = $render;
        $this->config = Singleton::getInstance();
    }

    /**
     * @param Request $request
     * @param Response $response
     * @return Response
     */
    public function paymentSettings(Request $request, Response $response){
        //Form
        $settingsForm = (new FormComponent())->src(Routes::getRoutePattern('payment.forms.admin.configuration'));

        //render
        $this->render::setPageTitle('Payment Configuration');
        $this->output::addResponse($request, $this->render::build([$settingsForm]));
        return System::asJson($response);
    }

    public function paymentRouting(Request $request, Response $response, $args){

        // 1. If has subscription product, send to payment terms
        //return $this->prePaymentTerms($request, $response, $args);

        // Else 2. send straight to Stripe via validation route.
        $this->output::addMetadata(
            'payment.routing.redirect',
            'redirectToExternal',
            rtrim($this->config->app->site->backend_domain, "/") . '/api/v1/payment/action/payment/validation?'.http_build_query($request->getQueryParams()));
        return System::asJson($response, []);
    }

    /**
     * @param Request $request
     * @param Response $response
     * @param $args
     * @return Response
     */
    public function prePaymentTerms(Request $request, Response $response, $args)
    {
        $queryParams = $request->getQueryParams();
        $params = json_decode(base64_decode($queryParams['args']));
        $userEntity = new userEntity();
        $userEntity->getUserByEmail(trim($params->userEmail));
        if (isset($userEntity->id) && $userEntity->id > 0 && isset($userEntity->marked_fraudulent) && $userEntity->marked_fraudulent > 0) {
            $paymentService = new paymentService();
            $paymentService->fraudAlertEmail(trim($params->userEmail));
            $this->output::addMetadata(
                'payment.terms.redirect',
                'redirect',
                Routes::getRoutePattern('payment.display.order-problem-fraud')
            );
            return System::asJson($response, []);
        }

        // Password Creation Form page to collect
        $this->render::setActive("paymentFlow");
        $this->render::setMetaTitle("Payment Terms | ". ($this->config->app->defaultMetaTitle ?? "Io Dashboard"));
        $wrapper = (new RowWrapper())->resetClasses()->addClass('payment-terms-wrapper')->addClass('container')->addComponent((new ContentTitle())
            ->addTitle('Terms and Conditions:')
            ->addContent(System::getVariable('io_payment_terms') ?? '')
        );
        if($termLink = System::getVariable('io_payment_terms_link')){
            $wrapper->addComponent((new BasicLink())->addRoute($termLink)->addText(System::getVariable('io_payment_terms_link_text')));        }

        $wrapper->addComponent((new FormComponent())->src(rtrim(Routes::getRoutePattern('payment.display.form.terms'),"/").'?'.http_build_query($request->getQueryParams()))
            ->addClass('accept-terms-form')->setID('accept-terms-form'));

        return System::asJson($response, $this->render::build([$wrapper]));
    }

    public function stopFraudulentTransaction(Request $request, Response $response, $args)
    {
        // Password Creation Form page to collect
        $this->render::setActive("paymentFlow");
        $this->render::setMetaTitle("Problem with your order | ". ($this->config->app->defaultMetaTitle ?? "Io Dashboard"));
        $wrapper = (new RowWrapper())->resetClasses()->addClass('payment-terms-wrapper')->addClass('container')
            ->addComponent((new ColWrapper())
                ->addClass('text-center')
                ->addComponent((new ContentTitle())
                    ->addTitle('There\'s a problem with your order')
                    ->addContent("We're very sorry, but there appears to be a problem with your order.<br><br>Please contact customer support, quoting the email address you used to place the order")
                )
                ->addComponent((new BasicLink())->addRoute('https://globalm2msim.zendesk.com/hc/en-us')->addText('Contact Customer Support')->addClass('btn btn-primary btn-lg text-center mt-4')->setID('contact-customer-support'))
            );

        return System::asJson($response, $this->render::build([$wrapper]));
    }

    /**
     * @param Request $request
     * @param Response $response
     * @param $args
     * @return Response
     */
    public function setupComplete(Request $request, Response $response, $args)
    {
        // Password Creation Form page to collect
        $this->render::setActive("paymentFlow");
        $this->render::setMetaTitle("Payment Setup Complete | ". ($this->config->app->defaultMetaTitle ?? "Io Dashboard"));
        $wrapper = (new RowWrapper())->resetClasses()->addClass('payment-terms-wrapper')->addClass('container')->addComponent((new ContentTitle())
            ->addTitle('Thank you - Payment setup complete')
            ->addContent(System::getVariable('io_payment_setup_complete_text') ?? 'Your payment method has been successfully setup, and will be used to make payments for your subscription.')
            )
            ->addComponent((new BasicLink())
                ->addRoute('/')
                ->addText('Sign in to the dashboard')
                ->addClass('text-center mt-4 sign-in-link btn btn-primary')
        );

        return System::asJson($response, $this->render::build([$wrapper]));
    }

    public function threeDSecure(Request $request, Response $response, $args)
    {
        $paymentEntity = new paymentEntity();
        $paymentEntity->loadByPublicId($args['publicId']);
        if (!isset($paymentEntity->id) || !$paymentEntity->id) { // Check record exists
            return System::asJson($response, ['error' => 'Not Found'], 404);
        }

        if ($paymentEntity->status != 'three_d_secure_required') {
            Logger::log('3ds_link_expired', $paymentEntity->getData());
            $this->render::setActive("paymentFlow");
            $this->render::setMetaTitle("Link Expired | ". ($this->config->app->defaultMetaTitle ?? "Io Dashboard"));
            $content = $paymentEntity->status == 'successful' ? 'Payment has already been taken successfully' : 'Payment could not be taken';
            $wrapper = (new RowWrapper())->resetClasses()->addClass('payment-terms-wrapper')->addClass('container')->addComponent((new ContentTitle())
                ->addTitle('This page has expired')
                ->addContent('The link is no longer valid. '.$content)
            );
            return System::asJson($response, $this->render::build([$wrapper]));
        }

        Logger::log('3ds_start_iframe', $paymentEntity->getData());

        // Password Creation Form page to collect
        $this->render::setActive("noUIiframe");
        $this->render::setMetaTitle("Payment 3D Secure | ". ($this->config->app->defaultMetaTitle ?? "Io Dashboard"));
        $wrapper = (new RowWrapper())->resetClasses()->addClass('threedsecure-wrapper')->addClass('container')
            ->addComponent((new Iframe())
                ->setSrc($paymentEntity->threedsecure_url)
                ->setTitle("3D Secure")
                ->addClass('h-100')
                ->addClass('w-100')
                ->addClass('position-absolute')
        );

        return System::asJson($response, $this->render::build([$wrapper]));
    }

    /**
     * @param Request $request
     * @param Response $response
     * @param $args
     * @return Response
     */
    public function threeDSecureComplete(Request $request, Response $response, $args)
    {
        $paymentEntity = new paymentEntity();
        $paymentEntity->loadByPublicId($args['publicId']);
        if (!isset($paymentEntity->id) || !$paymentEntity->id) { // Check record exists
            Logger::log('3ds_complete_payment_entity_not_found', ['public_id' => $args['publicId']]);
            return System::asJson($response, ['error' => 'Not Found'], 404);
        }

        $this->render::setActive("paymentFlow");

        switch ($paymentEntity->status){
            case 'successful':
                $this->render::setMetaTitle("Payment Complete | ". ($this->config->app->defaultMetaTitle ?? "Io Dashboard"));

                Logger::log('3ds_complete_success', $paymentEntity->getData());
                $wrapper = null;
                $wrapper = Hook::processHook('payment_3ds_success_message', $wrapper, $paymentEntity);

                if (!$wrapper) {
                    $wrapper = (new RowWrapper())->resetClasses()->addClass('payment-terms-wrapper')->addClass('container')->addComponent((new ContentTitle())
                        ->addTitle('Thank you - Payment complete')
                        ->addContent('Your subscription payment has now been confirmed.  You have successfully been charged £'.$paymentEntity->amount)
                    );
                }
                break;
            case 'three_d_secure_required':
                Logger::log('3ds_complete_auth_required', $paymentEntity->getData());
                $this->render::setMetaTitle("Payment Authorization Required | ". ($this->config->app->defaultMetaTitle ?? "Io Dashboard"));
                $reattemptLink = new BasicLink();
                $reattemptLink
                    ->addRoute($this->config->app->site->frontend_domain. Routes::getRoutePattern('payment.display.reattempt', ['publicId' => $args['publicId']]))
                    ->addText('Reattempt payment')
                    ->addClass('text-center btn btn-primary');

                $wrapper = (new RowWrapper())->resetClasses()->addClass('payment-terms-wrapper')->addClass('container')
                    ->addComponent((new ContentTitle())
                        ->addTitle('Payment Authorization Required')
                        ->addContent('Authorization could not be completed for payment of £' . $paymentEntity->amount . '<br>')
                    )->addComponent($reattemptLink)

                ;
                break;
            default:
                Logger::log('3ds_complete_payment_failed', $paymentEntity->getData());
                $this->render::setMetaTitle("Payment Failed | ". ($this->config->app->defaultMetaTitle ?? "Io Dashboard"));
                $wrapper = (new RowWrapper())->resetClasses()->addClass('payment-terms-wrapper')->addClass('container')->addComponent((new ContentTitle())
                    ->addTitle('Payment Failed')
                    ->addContent('Unfortunately your payment of £'. $paymentEntity->amount .' could not be authorised.')
                );
                break;
        }

        return System::asJson($response, $this->render::build([$wrapper]));
    }

    public function reattemptPayment(Request $request, Response $response, $args)
    {
        $paymentEntity = new paymentEntity();
        $paymentEntity->loadByPublicId($args['publicId']);
        if (!isset($paymentEntity->id) || !$paymentEntity->id) { // Check record exists
            return System::asJson($response, ['error' => 'Not Found'], 404);
        }

        if ($paymentEntity->status == 'successful') {
            $this->render::setMetaTitle("Payment Complete | ". ($this->config->app->defaultMetaTitle ?? "Io Dashboard"));
            $wrapper = (new RowWrapper())->resetClasses()->addClass('payment-terms-wrapper')->addClass('container')->addComponent((new ContentTitle())
                ->addTitle('Thank you - Payment complete')
                ->addContent('Your subscription payment has been confirmed.  You have successfully been charged £'.$paymentEntity->amount)
            );
            return System::asJson($response, $this->render::build([$wrapper]));
        }

        $paymentService = new paymentService();
        $newPaymentEntity = $paymentService->reattemptPayment($paymentEntity);

        if  (isset($newPaymentEntity->status) && $newPaymentEntity->status == 'three_d_secure_required') {
            $this->output::addMetadata(
                'payment.display.reattempt',
                'redirect',
                Routes::getRoutePattern('payment.display.threedsecure', ['publicId' => $newPaymentEntity->public_id])
            );
        } else {
            $this->output::addMetadata(
                'payment.display.reattempt',
                'redirect',
                Routes::getRoutePattern('payment.display.threedsecure-complete', ['publicId' => $newPaymentEntity->public_id])
            );
        }

        return System::asJson($response, []);
    }


}