<?php

namespace Mtc\Plugins\Judopay\Classes;

use Mtc\Core\Models\CountryState;
use Mtc\Modules\BlackList\Classes\BlackList;

class GPay
{
    private $basket;

    public function __construct(\Basket $basket)
    {
        $this->basket = $basket;        
    }

    public function getShippingOptions()
    {
        return array_map(function($v) {
            return [
                'id'            => strval($v['id']),
                'label'         => $v['name'],
                'description'   => "£{$this->basket->estimateDeliveryCost($v['id'], $this->basket->weight, $v['cost'])}",
            ];
        }, $this->basket->delivery_options);
    }

    public function getDisplayItems()
    {
        $items = array_map(function($v) {
            return [
                'label'         => "{$v['item_name']} (x{$v['quantity']})",
                'type'          => 'LINE_ITEM',
                'price'         => number_format((float) $v['line_total'], 2),
            ];
        }, $this->basket->items);

        $items[] = [
            'label'         => 'SubTotal',
            'type'          => 'SUBTOTAL',
            'price'         => number_format((float) $this->basket->cost_subtotal, 2),
        ];

        if($this->basket->delivery_selected
            && $this->basket->cost_delivery > 0) {
            $selected = collect($this->basket->delivery_options)
                ->where('id', $this->basket->delivery_selected)->first();

            if(!empty($selected['name'])) {
                $items[] = [
                    'label'         => $selected['name'],
                    'type'          => 'LINE_ITEM',
                    'price'         => number_format((float) $this->basket->cost_delivery, 2),
                ];
            }
        }

        $items[] = [
            'label'         => 'VAT',
            'type'          => 'TAX',
            'price'         => number_format((float) $this->basket->cost_vat, 2),
        ];

        return $items;
    }

    public function getTransactionInfo()
    {
        return [
            'displayItems'      => $this->getDisplayItems(),
            'totalPriceLabel'   => 'Total (Inc. VAT)',
            'totalPriceStatus'  => 'FINAL',
            'totalPrice'        => number_format($this->basket->cost_total, 2),
            'currencyCode'      => 'GBP',
            'countryCode'       => 'GB',
        ];
    }

    public function getPaymentDataRequest()
    {
        return [
            'apiVersion'        => 2,
            'apiVersionMinor'   => 0,
            'environment'       => config('judopay.testmode') ? 'TEST' : 'PRODUCTION',
            'merchantInfo'      => [
                'merchantId'    => judopayConfig('gpay.merchant_id'),
                'merchantName'  => config('app.name'),
            ],
            'allowedPaymentMethods' => [
                [
                    'type'          => 'CARD',
                    'parameters'    => [
                        'allowedCardNetworks'   => [
                            'MASTERCARD',
                            'VISA',
                            'AMEX',
                        ],
                        'allowedAuthMethods'    => [
                            'PAN_ONLY',
                            'CRYPTOGRAM_3DS'
                        ],
                        'billingAddressRequired'    => true,
                        'billingAddressParameters'  => [
                            'format'                => 'FULL',
                            'phoneNumberRequired'   => true
                        ],
                    ],
                    'tokenizationSpecification' => [
                        'type'          => 'PAYMENT_GATEWAY',
                        'parameters'    => [
                            'gateway'           => 'judopay',
                            'gatewayMerchantId' => strval(judopayConfig('merchant_id')),
                        ],
                    ],
                ],
            ],
            'callbackIntents'   => [
                'PAYMENT_AUTHORIZATION',
                'SHIPPING_ADDRESS',
                'SHIPPING_OPTION',
            ],
            'emailRequired'     => true,
            'shippingAddressRequired'   => true,
            'shippingAddressParameters' => [
                'phoneNumberRequired'   => true,
                'allowedCountryCodes'   => ['GB'],
            ],
            'shippingOptionRequired'    => true,
            'shippingOptionParameters'  => [
                'shippingOptions'       => $this->getShippingOptions(),
                'defaultSelectedOptionId'=> strval($this->basket->delivery_selected),
            ],
            'transactionInfo'   => $this->getTransactionInfo(),
        ];
    }

    public function getPaymentDataRequestUpdate()
    {
        $error = current($this->validateBasket([
            'address'       => true,
        ]));

        return [
            'newShippingOptionParameters'   => [
                'shippingOptions'       => $this->getShippingOptions(),
                'defaultSelectedOptionId'=> strval($this->basket->delivery_selected),
            ],
            'newTransactionInfo'            => $this->getTransactionInfo(),
            'error'                         => $error,
        ];
    }

    public function validateBasket(array $exclude = [])
    {
        global $member, $basket_countries;

        if(empty($member->id)) {
            return [
                [
                    'reason'        => 'OTHER_ERROR',
                    'message'       => 'You are not logged in on the website!',
                ],
            ];
        }

        $errors = [];

        if(!empty($this->basket->require_id_check)) {
            $errors[] = [
                'reason'        => 'OTHER_ERROR',
                'message'       => 'ID check is required on the website!',
            ];
        }

        $validation = $this->basket->validate([
            'basket'    => (array) $this->basket,
            'terms'     => true,
        ], $basket_countries, CountryState::getCountryStateList());

        foreach ($validation as $key => $value) {
            switch($key) {
                case 'terms':
                    break;
                case 'address':
                    if(!empty($exclude['address'])) break;

                    foreach($value as $type => $fields) {
                        foreach($fields as $name => $message) {
                            switch($name) {
                                case 'postcode':
                                case 'country':
                                    $errors[] = [
                                        'reason'    => $type == 'billing' ? 'SHIPPING_ADDRESS_INVALID' : 'SHIPPING_ADDRESS_UNSERVICEABLE',
                                        'message'   => $message,
                                    ];
                                    break 3;
                                default:
                                    $errors[] = [
                                        'reason'    => 'SHIPPING_ADDRESS_INVALID',
                                        'message'   => "We're sorry we are unable to process this order due to incorrect details. If you think this is an error, please contact us",
                                    ];
                                    break 3;
                            }
                        }
                        
                    }
                    break;
                default:
                    $errors[] = [
                        'reason'    => 'OTHER_ERROR',
                        'message'   => "We're sorry we are unable to process this order due to incorrect details. If you think this is an error, please contact us {$key}",
                    ];
                    break;
            }
        }

        $blacklist = new BlackList();
        $blacklist_flag_type = $blacklist->isBlacklisted([
            'telephone' => $this->basket->info['contact_no'],
            'email' => $this->basket->info['email'],
            'address' => $this->basket->address['billing']['postcode']
        ]);

        if($blacklist_flag_type > 0) {
            $this->basket->addBasketFlag($blacklist_flag_type);
        }

        if ($blacklist_flag_type === BlackList::HARD_BLACKLIST_FLAG) {
            $errors[] = [
                'reson'         => 'OTHER_ERROR',
                'message'       => "We're sorry we are unable to process this order due to suspected account misuse. If you think this is an error, please contact us",
            ];
        }

        if(!empty($this->basket->delivery_error)) {
            $errors[] = [
                'reson'         => 'SHIPPING_ADDRESS_UNSERVICEABLE',
                'message'       => $this->basket->delivery_error,
            ];
        }

        return $errors;
    }

    public function mapErrors(array $errors)
    {
        $r = [];

        // array_walk_recursive($errors, function($value, $key) use(&$r) {
        //     $r[] = [
        //         'reason'        => 'PAYMENT_DATA_INVALID',
        //         'message'       => "{$key} - {$value}",
        //         'intent'        => 'PAYMENT_AUTHORIZATION',
        //     ];
        // });

        return $r;
    }
}