<?php

namespace Mtc\Plugins\Judopay\Classes;

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

class APay
{
    private $basket;

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

    public function getShippingOptions()
    {
        return array_map(function($v) {
            return [
                'identifier'    => $v['id'],
                'label'         => $v['name'],
                'detail'        => '',
                'amount'        => number_format($this->basket->estimateDeliveryCost($v['id'], $this->basket->weight, $v['cost']), 2),
            ];
        }, $this->basket->delivery_options);
    }

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

        $items[] = [
            'label'         => 'SubTotal',
            'amount'        => number_format($this->basket->cost_subtotal, 2),
        ];

        if(!empty($this->basket->delivery_selected)) {
            $items[] = [
                'label'         => collect($this->basket->delivery_options)
                    ->where('id', $this->basket->delivery_selected)->first()['name'],
                'amount'        => number_format($this->basket->cost_delivery, 2),
            ];
        }

        $items[] = [
            'label'         => 'VAT',
            'amount'        => number_format($this->basket->cost_vat, 2),
        ];

        return $items;
    }

    public function getDetails()
    {
        return [
            'total'             => $this->getTotal(),
            'lineItems'         => $this->getDisplayItems(),
            'shippingOptions'   => $this->getShippingOptions(),
        ];
    }

    public function getTotal()
    {
        return [
            'label'         => 'Pay ' . config('app.name'),
            'amount'        => number_format($this->basket->cost_total, 2),
            'type'          => 'final',
        ];
    }

    public function getPaymentDataRequest()
    {
        return [
            'countryCode'           => 'GB',
            'currencyCode'          => 'GBP',
            'merchantCapabilities'  => [
                'supports3DS',
            ],
            'supportedNetworks' => [
                'amex',
                'discover',
                'masterCard',
                'visa',
            ],
            'requiredBillingContactFields' => [
                'postalAddress',
                'name',
                'phone',
                'email',
            ],
            'requiredShippingContactFields' => [
                'postalAddress',
                'name',
                'phone',
                'email'
            ],
            'shippingType'          => 'shipping',
            'shippingMethods'       => $this->getShippingOptions(),
            'lineItems'             => $this->getDisplayItems(),
            'total'                 => $this->getTotal(),
        ];
    }

    public function getPaymentDataRequestUpdate()
    {
        return [
            'newTotal'             => $this->getTotal(),
            'newLineItems'         => $this->getDisplayItems(),
            'newShippingOptions'   => $this->getShippingOptions(),
        ];
    }

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

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

        $errors = [];

        if(!empty($this->basket->require_id_check)) {
            $errors[] = [
                'code'          => 'billingContactInvalid',
                'field'         => 'name',
                '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;

                    $contactFields = [
                        'postcode'      => 'postalAddress',
                        'city'          => 'locality',
                        'country'       => 'country',
                    ];

                    foreach($value as $type => $fields) {
                        foreach($fields as $name => $message) {
                            switch($name) {
                                case 'postcode':
                                case 'country':
                                    $errors[] = [
                                        'code'      => $type == 'billing' ? 'billingContactInvalid' : 'addressUnserviceable',
                                        'field'     => $contactFields[$name] ?? 'name',
                                        'message'   => $message,
                                    ];
                                    break 3;
                                default:
                                    $errors[] = [
                                        'code'      => $type == 'billing' ? 'billingContactInvalid' : 'shippingContactInvalid',
                                        'field'     => $contactFields[$name] ?? 'name',
                                        '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[] = [
                        'code'      => 'billingContactInvalid',
                        'field'     => 'name',
                        '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;
            }
        }

        $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[] = [
                'code'          => 'billingContactInvalid',
                'field'         => 'postalAddress',
                '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)
            && $this->basket->cost_delivery > 0) {
            $errors[] = [
                'code'          => 'addressUnserviceable',
                'field'         => 'shippingContact',
                'message'       => $this->basket->delivery_error,
            ];
        }

        return $errors;
    }

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

        array_walk_recursive($errors, function($value, $key) use(&$r) {
            $r[] = [
                'code'          => 'shippingContactInvalid',
                'field'         => 'emailAddress',
                'message'       => "{$key} - {$value}",
            ];
        });

        return $r;
    }
}