<?php

namespace apexl\Io\modules\paymentDisplay\controllers;

use apexl\Config\Singleton;
use apexl\encryption\Encrypt;
use apexl\Io\includes\Controller;
use apexl\Io\includes\Routes;
use apexl\Io\includes\System;
use apexl\Io\modules\display\components\BasicLink;
use apexl\Io\modules\display\components\CardEntityFilteredDisplayTable;
use apexl\Io\modules\display\components\ColWrapper;
use apexl\Io\modules\display\components\ComponentWrapper;
use apexl\Io\modules\display\components\ContentTitle;
use apexl\Io\modules\display\components\DateSelectWrapper;
use apexl\Io\modules\display\components\DisplayTable;
use apexl\Io\modules\display\components\EntityDisplayTile;
use apexl\Io\modules\display\components\EntityFilteredDisplayTable;
use apexl\Io\modules\display\components\FilteredChild;
use apexl\Io\modules\display\components\FilterForm;
use apexl\Io\modules\display\components\FormComponent;
use apexl\Io\modules\display\components\genericComponents;
use apexl\Io\modules\display\components\RowWrapper;
use apexl\Io\modules\display\services\Render;
use apexl\Io\modules\invoice\services\invoiceService;
use apexl\Io\modules\payment\entities\paymentEntity;
use apexl\Io\modules\payment\entities\paymentTokenEntity;
use apexl\Io\modules\payment\entities\userCreditEntity;
use apexl\Io\modules\payment\providers\stripeProvider;
use apexl\Io\modules\payment\services\cardValidationService;

use apexl\Io\modules\payment\services\paymentService;
use apexl\Io\modules\payment\services\woocommerceIntegrationService;
use apexl\Io\modules\paymentDisplay\components\viewTiles;
use apexl\Io\modules\subscription\entities\subscriptionEntity;
use apexl\Io\modules\subscription\services\subscriptionService;
use apexl\Io\modules\user\entities\userEntity;
use apexl\Io\modules\user\services\currentUser;
use apexl\Io\modules\user\services\userTools;
use app\module\simcard\entities\simOrderEntity;
use app\module\simcard\entities\simOrderItemEntity;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

class paymentTokenController extends Controller{

    protected $currentUser;

    public function __construct(currentUser $currentUser, Render $render)
    {
        parent::__construct();
        $this->currentUser = $currentUser::getCurrentUser();
        $this->render = $render;
    }

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

        $currentUser = currentUser::getCurrentUser();
        if ($currentUser->isAllowed('ViewAllAccounts')) {
            return $this->paymentAdminDashboard($request, $response, $args);
        }

        $paymentService = new paymentService();
        $invoiceService = new invoiceService();
        $components = [];

        /*if($currentUser->isAllowed('ManageUsers')) {
            $filterForm = (new RowWrapper())
                ->addComponent((new FilterForm())->isShared()->src(Routes::getRoutePattern('payment.display.forms.filter-payment-details')));
            $components[] = $filterForm;
        }*/

        $subscriptionTable = \apexl\Io\modules\subscriptionDisplay\components\viewTiles::userSubscriptionsTile($currentUser);
        $paymentsTable = \apexl\Io\modules\paymentDisplay\components\viewTiles::latestPaymentsTile($currentUser);

        $cardsTable = (new CardEntityFilteredDisplayTable((new paymentTokenEntity()), [], false, 'dropmenu'))
            ->addTitle('Payment Cards')
            ->src(Routes::getRoutePattern('paymentToken.data.basic'))
            ->displayPagination(FALSE)
            ->displayShortTotals(FALSE)
            ->addClass('col-12 col-lg-12 col-xl-12')
            ->hideIdColumn();
        $cardsTable->addDropMenuModal('edit', 'Edit Card', [], 'paymentTokenEntity.display.put');
        $cardsTable->addDropMenuModal('delete', 'Delete Card', [], 'paymentTokenEntity.display.delete');

        $paymentService = new paymentService();
        $newCardbutton = new BasicLink();
        $newCardbutton->addRoute($paymentService->getCardSetupLink($currentUser));
        $newCardbutton->addText('Add New Card');
        $newCardbutton->addClass('add-new-card-button btn btn-primary text-center w-100');

        $subscriptionsList = new ColWrapper();
        $subscriptionsList->addClass('col-sm-12 col-xl-8');
        $subscriptionsList->addComponents([
            $subscriptionTable, $paymentsTable
        ]);

        $cardsList = new ColWrapper();
        $cardsList->addClass('col-sm-12 col-xl-4');
        if ($invoiceService->getTotalCredit($currentUser->id) > 0) {
        $cardsTitle = new ContentTitle();
            $cardsTitle->addContent("Available credit: <strong>£{$invoiceService->getTotalCredit($currentUser->id)}</strong>");
            $cardsTitle->addClass('mb-4');
            $cardsList->addComponent($cardsTitle);
        }
        $cardsList->addComponents([
            $cardsTable,
            $newCardbutton
        ]);
        $content = (new RowWrapper())
            ->addComponent($subscriptionsList)
            ->addComponent($cardsList)
        ;

        $components[] = $content;

        $this->render::setPageTitle('Payment Details');

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

    public function paymentAdminDashboard(Request $request, Response $response, $args)
    {
        // Dates
        $start = (isset($args['startDate']) && $args['startDate']) ? \DateTime::createFromFormat('Y-m-d', $args['startDate']) . ' 00:00:00' : new \DateTime('first day of this month');
        $end = (isset($args['endDate']) && $args['endDate']) ? \DateTime::createFromFormat('Y-m-d', $args['endDate']) . ' 23:59:59' : new \DateTime('last day of this month');

        $wrapper = (new DateSelectWrapper())
            ->setStartDate($start)
            ->setEndDate($end)
            ->addComponent(
                (new FilteredChild())
                    ->setContentSrc('payment.display.payment-details-admin-content')
            )
        ;

        $this->render::setPageTitle('Admin - Payments');
        return System::asJson($response, $this->render::build($wrapper));
    }

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

        $start = \DateTime::createFromFormat('Y-m-d H:i:s', $args['startDate'] . ' 00:00:00');
        $end = \DateTime::createFromFormat('Y-m-d H:i:s', $args['endDate'] . ' 23:59:59');

        $components = [];

        $simOrderEntity = new simOrderEntity();
        $salesFigures = $simOrderEntity->getSalesFiguresForDates($start, $end);

        $simOrderItemEntity = new simOrderItemEntity();
        $bestsellerInfo = $simOrderItemEntity->getBestsellerInfo($start, $end);

        $subscriptionService = new subscriptionService();
        $subscriptionBestseller = $subscriptionService->getBestsellerInfo($start, $end);

//print_r($subscriptionBestseller);
//print_r($bestsellerInfo);die();



        // Panel 1 - Sales
        $col1Wrapper = (new ColWrapper())->addClass('sales-summary col-12 col-xl-4');
        $col1Wrapper->addComponents([
            (new ContentTitle())->addTitle('Sales')->addContent('£'.number_format($salesFigures->salesTotal, 2) . '<br><small>Total Sales Between '.$start->format('jS F Y').' and '.$end->format('jS F Y').'</small>'),
            (new ContentTitle())->addTitle('Total Orders')->addContent($salesFigures->salesCount),
            (new ContentTitle())->addTitle('Average Sales per order')->addContent('£'.number_format($salesFigures->salesAverage, 2)),
        ]);
        $components[] = $col1Wrapper;

        // Panel 2 - Top product by volume
        $col2Wrapper = (new ColWrapper())->addClass('top-product-by-volume col-12  col-xl-4');
        $col2Wrapper->addComponents([
            (new ContentTitle())->addTitle('Top Product By Volume')->addContent($bestsellerInfo->byVolume->name),
            (new ContentTitle())->addTitle('Quantity Purchased')->addContent((string)($salesFigures->salesQuantity ?? 0)),
        ]);
        $components[] = $col2Wrapper;

        // Panel 3 - Top product by value
        $col3Wrapper = (new ColWrapper())->addClass('top-product-by-value col-12  col-xl-4');
        $col3Wrapper->addComponents([
            (new ContentTitle())->addTitle('Top Product By Value')->addContent($bestsellerInfo->byValue->value > $subscriptionBestseller->valueRaw ? $bestsellerInfo->byValue->name : $subscriptionBestseller->name),
            (new ContentTitle())->addTitle('Total Value')->addContent('£'.number_format($bestsellerInfo->byValue->value > $subscriptionBestseller->valueRaw ? $bestsellerInfo->byValue->value : $subscriptionBestseller->valueRaw, 2)),
        ]);
        $components[] = $col3Wrapper;

        $components[] = (new ColWrapper())->addClass('latest-invoices col-12  col-xl-8')
            ->addComponent(\apexl\Io\modules\invoiceDisplay\components\dashboardTiles::userInvoicesTile(null, $start, $end));


        //$col4Wrapper = (new ColWrapper())->addClass('bg-white latest-payments');
        //$paymentsTable = \apexl\Io\modules\paymentDisplay\components\viewTiles::latestPaymentsTile();
        //$col4Wrapper->addComponent($paymentsTable);
        //$components[] = $col4Wrapper;

        $components[] = (new ColWrapper())->addClass('sales-breakdown-chart col-12  col-xl-4')
            ->addComponent(\apexl\Io\modules\paymentDisplay\components\viewTiles::salesBreakdownChart($start, $end));

        $wrapper = (new RowWrapper())
            ->addComponents($components);

        $this->render::setActive("modal"); // Use modal as only want to render the components, not the nav etc.
        return System::asJson($response, $this->render::build($wrapper));
    }


    /**
     * @param Request $request
     * @param Response $response
     * @param array $args
     * @return Response
     * @throws \Exception
     */
    public function updatePaymentToken(Request $request, Response $response, $args = []){

        $paymentTokenEntity = new paymentTokenEntity();
        $title= "";
        $components = [];

        if($id = $args[$paymentTokenEntity->primaryKey] ?? FALSE){
            $paymentTokenEntity->load($id);
            $title = 'Edit Card #'. $paymentTokenEntity->id;
            if ($this->currentUser->id == $paymentTokenEntity->user_id || $this->currentUser->isAllowed('AccessGlobalEntities')) {
                $components = (new FormComponent())->setID('updatePaymentToken')->src(Routes::getRoutePattern('payment.display.forms.update-card', $args));
            }
        }

        $this->render::setActive("modal");
        $this->render::setPageTitle($title);
        $this->output::addResponse($request, $this->render::build($components));
        return System::asJson($response);
    }

    /**
     * @param Request $request
     * @param Response $response
     * @param array $args
     * @return Response
     * @throws \Exception
     */
    public function deletePaymentToken(Request $request, Response $response, $args = []){

        $paymentTokenEntity = new paymentTokenEntity();
        $title= "";
        $components = [];

        if($id = $args[$paymentTokenEntity->primaryKey] ?? FALSE){
            $paymentTokenEntity->load($id);
            $title = 'Edit Card #'. $paymentTokenEntity->id;
            if ($this->currentUser->id == $paymentTokenEntity->user_id || $this->currentUser->isAllowed('AccessGlobalEntities') || $this->currentUser->hasRole(1)) {

                $config = Singleton::getInstance();
                $stripe = new stripeProvider();
                $encrypt = new Encrypt();

                $allBillingTokens = $paymentTokenEntity->getAllActiveForUser($paymentTokenEntity->user_id);

                if (count($allBillingTokens) < 2) {
                    $components[] = (new ContentTitle())
                        ->addTitle('Payment method cannot be removed')
                        ->addContent('You must have at least one payment method in order to pay for any outstanding subscription and overage fees. If you wish to add a new payment method, please click the "Add New Card" button on the Payment Details page.  You will then be allowed to remove this card.');

                } else {

                $paymentMethodRefDecrypted = $encrypt->decrypt($paymentTokenEntity->payment_method_ref, $paymentTokenEntity->payment_method_ref_iv, $config->app->encryption->key);
                if ($paymentMethod = $stripe->getPaymentMethod($paymentMethodRefDecrypted)) {
                    $basicInfo = new DisplayTable();
                    $basicInfo->addTitle("Are you sure you want to delete this payment method?");
                    $basicInfo->addData('ID', $paymentTokenEntity->id);
                    $basicInfo->addData('Type', $paymentMethod->card->brand);
                    $basicInfo->addData('Name', $paymentTokenEntity->ref);
                    $basicInfo->addData('Description', ucfirst($paymentMethod->card->funding) . ' card ending in **** '.$paymentMethod->card->last4 . '<br>expires: '.$paymentMethod->card->exp_month.'/'.$paymentMethod->card->exp_year);
                    $components[] = $basicInfo;
                }

                $components[] = (new FormComponent())
                    ->src(Routes::getRoutePattern('payment.display.forms.delete-card', ['id' => $id]))
                    ->header(3);
                $title = 'Confirm Payment Method Deletion:';
                }

                $components = (new RowWrapper())->addClass('delete-token-wrapper')
                    ->addComponents($components);
            }
        }

        $this->render::setPageTitle($title);
        $this->render::setActive("modal");
        $this->output::addResponse($request, $this->render::build($components));
        return System::asJson($response);
    }

}