<?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): void {
            $r[] = [
                'code' => 'shippingContactInvalid',
                'field' => 'emailAddress',
                'message' => "{$key} - {$value}",
            ];
        });

        return $r;
    }
}
