<?php

namespace Autogedal\TbiBank\Test\Unit;

use Autogedal\TbiBank\Model\ApplicationRegistry;
use Autogedal\TbiBank\Model\ApprovalAccounting;
use Autogedal\TbiBank\Model\ApprovalConfig;
use Autogedal\TbiBank\Model\Environment;
use Autogedal\TbiBank\Plugin\OrderEmail;
use Autogedal\TbiBank\Plugin\RegistrationResult;
use Magento\Framework\HTTP\Client\Curl;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Email\Sender\OrderSender;
use Magento\Sales\Model\Order\Payment;
use PHPUnit\Framework\TestCase;
use TbiBank\FusionPay\Model\Cryptor;

class RegistrationAndEmailTest extends TestCase
{
    public function testSuccessfulRegistrationRetainsApplicationIdTokenAndMerchantIdentity(): void
    {
        $environment = $this->createMock(Environment::class);
        $environment->method('getOrigin')->willReturn(Environment::UAT_ORIGIN);
        $environment->method('getCredentials')->willReturn(['reseller_code' => 'test', 'reseller_key' => 'key', 'encryption_key' => 'synthetic']);
        $registry = $this->createMock(ApplicationRegistry::class);
        $registry->expects($this->once())->method('save')->with('AGD-123', 60, 'provider-token');
        $curl = $this->createMock(Curl::class);
        $curl->method('getStatus')->willReturn(200);
        $curl->method('getBody')->willReturn(json_encode(['error' => 0, 'order_id' => 60, 'token' => 'provider-token']));
        $request = json_encode(['reseller_code' => 'test', 'reseller_key' => 'key',
            'data' => Cryptor::Encrypt(json_encode(['orderid' => 'AGD-123']), 'synthetic')]);
        $this->assertNull((new RegistrationResult($registry, $environment))->afterPost($curl, null,
            Environment::UAT_ORIGIN . '/api/RegisterApplication', $request));
    }

    public function testOtherHttpCallsDoNotReadTbiConfiguration(): void
    {
        $environment = $this->createMock(Environment::class);
        $environment->expects($this->never())->method('getOrigin');
        $registry = $this->createMock(ApplicationRegistry::class);
        $registry->expects($this->never())->method('save');
        $result = (new RegistrationResult($registry, $environment))->afterPost($this->createMock(Curl::class),
            'original', 'https://example.test/other', '{}');
        $this->assertSame('original', $result);
    }

    /** @dataProvider emailCases */
    public function testOrderEmailDeferralIsTbiSpecificAndConfigurable(string $method, bool $approved, bool $defer, bool $expected): void
    {
        $config = $this->createMock(ApprovalConfig::class);
        $config->method('deferOrderEmail')->willReturn($defer);
        $payment = $this->createPartialMock(Payment::class, []);
        $payment->setMethod($method)->setAdditionalInformation(ApprovalAccounting::MARKER, $approved);
        $order = $this->createPartialMock(Order::class, ['getPayment']);
        $order->method('getPayment')->willReturn($payment);
        $called = false;
        $result = (new OrderEmail($config))->aroundSend($this->createMock(OrderSender::class),
            function ($passed, $force) use (&$called, $order) {
                $this->assertSame($order, $passed);
                $this->assertFalse($force);
                $called = true;
                return true;
            }, $order);
        $this->assertSame($expected, $called);
        $this->assertSame($expected, $result);
    }

    public static function emailCases(): array
    {
        return [['fusionpay', false, true, false], ['fusionpay', true, true, true],
            ['fusionpay', false, false, true], ['cashondelivery', false, true, true]];
    }
}
