<?php

namespace Alsendo\AlsendoWrapper\Tests\Unit\Api\Ecolet;


use Alsendo\AlsendoWrapper\Api\Apaczka\Model\Order\Valuation\ApaczkaOrderValuation;
use Alsendo\AlsendoWrapper\Api\Ecolet\EcoletOAuthClient;
use Alsendo\AlsendoWrapper\Api\Ecolet\EcoletTokenStorage;
use Alsendo\AlsendoWrapper\Api\Ecolet\Model\Order\EcoletOrderResponse;
use Alsendo\AlsendoWrapper\Api\Ecolet\Model\Order\EcoletOrderValuation;
use Alsendo\AlsendoWrapper\ApiClientFactory;
use Alsendo\AlsendoWrapper\ApiClientInterface;
use Alsendo\AlsendoWrapper\Model\Address;
use Alsendo\AlsendoWrapper\Model\Cod;
use Alsendo\AlsendoWrapper\Model\Contact;
use Alsendo\AlsendoWrapper\Model\Notification;
use Alsendo\AlsendoWrapper\Model\NotificationDetail;
use Alsendo\AlsendoWrapper\Model\Order\Created\OrderCreatedResponse;
use Alsendo\AlsendoWrapper\Model\Order\OrderRequest;
use Alsendo\AlsendoWrapper\Model\Pickup;
use Alsendo\AlsendoWrapper\Model\Service\ServiceStructure;
use Alsendo\AlsendoWrapper\Model\Shipment;
use DateTimeImmutable;
use Dotenv\Dotenv;
use Faker\Factory;
use PHPUnit\Framework\TestCase;

class ApiEcoletTest extends TestCase
{
    private ApiClientInterface $apiClient;

    private EcoletOAuthClient $ecoletOAuthClient;

    private EcoletTokenStorage $tokenStorage;

    private $faker;
    private ?int $orderId = null;

    protected function setUp(): void
    {
        // Ładowanie zmiennych z pliku .env
        $dotenv = Dotenv::createImmutable(__DIR__ . '/../../../../', '.env.test.local');
        $dotenv->load();

        $this->ecoletOAuthClient = new EcoletOAuthClient(
            [
                'client_id' => $_ENV['ECOLET_API_CLIENT_ID'],
                'client_secret' => $_ENV['ECOLET_API_CLIENT_SECRET'],
                'redirect_uri' => $_ENV['ECOLET_API_REDIRECT_URI'],
            ],
            true
        );

        $token = $this->ecoletOAuthClient->getAccessTokenWithPassword($_ENV['ECOLET_API_USERNAME'], $_ENV['ECOLET_API_PASSWORD']);

        $this->tokenStorage = new EcoletTokenStorage('ecolet_token.json');
        $this->tokenStorage->saveToken($token);

        $this->apiClient = (new ApiClientFactory())->create(
            ApiClientFactory::ECOLET_TEST,
            [
                'token' => $this->tokenStorage->getToken()->getAccessToken(),
            ]);

        $this->faker = Factory::create();
        $this->faker->addProvider(new \Faker\Provider\ro_RO\Address($this->faker));
        $this->faker->addProvider(new \Faker\Provider\ro_RO\PhoneNumber($this->faker));
        $this->faker->addProvider(new \Faker\Provider\ro_RO\Person($this->faker));
    }

    public function testGetMe(): void
    {
        $response = $this->apiClient->getMe();

        $this->assertIsArray($response);
    }

    /**
     */
    public function testSendOrder(): void
    {
        $orderRequest = new OrderRequest();
        // Set up the order request data
        $orderRequest->serviceId = 'dpd_standard';

        $orderRequest->address = new Address(
            new Contact(
                'ro',
                'Test Company',
                '',
                '',
                '011318',
                'Bucuresti',
                'Bucuresti',
                1,
                'Test Test',
                'test@ecolet.ro',
                '0214824089',
                '',
                13751,
                'Bucuresti-Ploiesti',
                '172-176',
                '1',
                'A2',
                '1',
                'A3a',
                false,
                null
            ),
            new Contact(
                'ro',
                'Test Company',
                '',
                '',
                '011318',
                'Bucuresti',
                'Bucuresti',
                1,
                'Test Test',
                'test@ecolet.ro',
                '0214824089',
                '',
                13751,
                'Bucuresti-Ploiesti',
                '172-176',
                '1',
                'A2',
                '1',
                'A3a',
                false,
                null
            )
        );

        $orderRequest->shipmentValue = 200;

        $orderRequest->cod = new Cod();

        $orderRequest->cod->amount = 0;
        $orderRequest->cod->bankAccount = '';

        $orderRequest->pickup = new Pickup();

        $orderRequest->pickup->type = 'courier';
        $orderRequest->pickup->date = (new DateTimeImmutable('+1 day'))->format('Y-m-d');
        $orderRequest->pickup->hoursFrom = '13:00';

        $shipment = new Shipment();
        $shipment->dimension1 = 10;
        $shipment->dimension2 = 10;
        $shipment->dimension3 = 10;
        $shipment->weight = 10;
        $shipment->isNstd = 0;
        $shipment->shipmentTypeCode = 'package';
        $shipment->shape = 'standard';
        $shipment->amount = null;
        $shipment->content = 'book';
        $orderRequest->shipment[] = $shipment;

        $orderRequest->content = 'book';

        $token = $this->tokenStorage->getToken();
        if ($token && $token->isExpired()) {
            $newToken = $this->ecoletOAuthClient->refreshAccessToken($token->refreshToken);
            if ($newToken) {
                $this->tokenStorage->saveToken($newToken);
            }
        }
        $response = $this->apiClient->sendOrder($orderRequest);
        $this->assertInstanceOf(EcoletOrderResponse::class, $response);
    }

    public function testGetOrderValuation(): void
    {
        $orderRequest = new OrderRequest();
        // Set up the order request data
        $orderRequest->serviceId = 'dpd_standard';

        $orderRequest->address = new Address(
            new Contact(
                'ro',
                'Test Company',
                '',
                '',
                '011318',
                'Bucuresti',
                'Bucuresti',
                1,
                'Test Test',
                'test@ecolet.ro',
                '0214824089',
                '',
                13751,
                'Bucuresti-Ploiesti',
                '172-176',
                '1',
                'A2',
                '1',
                'A3a',
                false,
                null
            ),
            new Contact(
                'ro',
                'Test Company',
                '',
                '',
                '011318',
                'Bucuresti',
                'Bucuresti',
                1,
                'Test Test',
                'test@ecolet.ro',
                '0214824089',
                '',
                13751,
                'Bucuresti-Ploiesti',
                '172-176',
                '1',
                'A2',
                '1',
                'A3a',
                false,
                null
            )
        );

        $orderRequest->shipmentValue = 200;

        $orderRequest->cod = new Cod();

        $orderRequest->cod->amount = 0;
        $orderRequest->cod->bankAccount = '';

        $orderRequest->pickup = new Pickup();

        $orderRequest->pickup->type = 'courier';
        $orderRequest->pickup->date = (new DateTimeImmutable('+1 day'))->format('Y-m-d');
        $orderRequest->pickup->hoursFrom = '13:00';

        $shipment = new Shipment();
        $shipment->dimension1 = 10;
        $shipment->dimension2 = 10;
        $shipment->dimension3 = 10;
        $shipment->weight = 10;
        $shipment->isNstd = 0;
        $shipment->shipmentTypeCode = 'package';
        $shipment->shape = 'standard';
        $shipment->amount = null;
        $shipment->content = 'book';
        $orderRequest->shipment[] = $shipment;

        $orderRequest->content = 'book';

        $token = $this->tokenStorage->getToken();
        if ($token && $token->isExpired()) {
            $newToken = $this->ecoletOAuthClient->refreshAccessToken($token->refreshToken);
            if ($newToken) {
                $this->tokenStorage->saveToken($newToken);
            }
        }
        $response = $this->apiClient->getOrderValuation($orderRequest);
        fwrite(STDERR, var_export($response, true));
        $this->assertInstanceOf(EcoletOrderValuation::class, $response);
    }

    public function testGetServiceStructure()
    {
        $response = $this->apiClient->getServiceStructure();
        fwrite(STDERR, var_export($response, true));
        $this->assertInstanceOf(ServiceStructure::class, $response);
    }

    public function testGetOrder(): void
    {
        $orderId = $this->orderId ?? 2223205;
        $response = $this->apiClient->getOrder($orderId);
        $this->assertInstanceOf(EcoletOrderResponse::class, $response);
    }


}