<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

use GuzzleHttp\Client;
use GuzzleHttp\Middleware;
use GuzzleHttp\HandlerStack;


use CorpusParole\Libraries\Handle\HandleClient;

class HandleClientIntegrationTest extends TestCase
{

    public function setUp() {
        parent::setUp();

        $this->handleHost = env('HANDLE_HOST', null);
        $this->handlePort = env('HANDLE_PORT', 8000);

        if(empty($this->handleHost)) {
            $this->markTestSkipped('Handle host empty');
        }

        $this->testPrefix = env('HANDLE_TEST_PREFIX', null);
        if(empty($this->testPrefix)) {
            $this->markTestSkipped('Handle test prefix not defined');
        }

        $certPem = env('HANDLE_TEST_CERT', null);
        $this->certPemPassword = env('HANDLE_TEST_CERT_PASSWORD', null);
        $this->certAdminHandle = env('HANDLE_TEST_CERT_ADMIN_HANDLE', null);
        if(empty($certPem) || empty($this->certAdminHandle)) {
            $this->markTestSkipped('Handle test certificate or user is empty');
        }

        $dsaPem = env('HANDLE_TEST_DSA_KEY', null);
        $this->dsaPemPassword = env('HANDLE_TEST_DSA_PASSWORD', null);
        $this->dsaAdminHandle = env('HANDLE_TEST_DSA_ADMIN_HANDLE', null);
        if(empty($dsaPem) || empty($this->dsaAdminHandle)) {
            $this->markTestSkipped('Handle dsa key or user not set');
        }
        $this->dsaAdminRawHandle = str_replace("300:", "", $this->dsaAdminHandle);

        $rsaPem = env('HANDLE_TEST_RSA_KEY', null);
        $this->rsaPemPassword = env('HANDLE_TEST_RSA_PASSWORD', null);
        $this->rsaAdminHandle = env('HANDLE_TEST_RSA_ADMIN_HANDLE', null);
        if(empty($rsaPem) || empty($this->rsaAdminHandle)) {
            $this->markTestSkipped('Handle rsa key or user not set');
        }
        $this->rsaAdminRawHandle = str_replace("300:", "", $this->rsaAdminHandle);

        $this->filesToDelete = [];

        if(is_file($certPem)) {
            $this->certTmpPath = $certPem;
        } else {
            $this->certTmpPath = tempnam("/tmp", "CERT_TEST");
            array_push($this->filesToDelete,$this->certTmpPath);
            file_put_contents($this->certTmpPath, $certPem);
        }

        if(is_file($dsaPem)) {
            $this->dsaTmpPath = $dsaPem;
        } else {
            $this->dsaTmpPath = tempnam("/tmp", "DSA_TEST");
            array_push($this->filesToDelete,$this->dsaTmpPath);
            file_put_contents($this->dsaTmpPath, $dsaPem);
        }

        if(is_file($rsaPem)) {
            $this->rsaTmpPath = $rsaPem;
        } else {
            $this->rsaTmpPath = tempnam("/tmp", "RSA_TEST");
            array_push($this->filesToDelete,$this->rsaTmpPath);
            file_put_contents($this->rsaTmpPath, $rsaPem);
        }

        // Create a middleware that echoes parts of the request.
        // $tapMiddleware = Middleware::tap(function ($request) {
        //     echo "\n+++++++++++++++++\nREQ HEADERS : ".print_r($request->getHeaders(), true)."\n+++++++++++++++++++\n";
        //     echo "\n------------------\nREQ BODY : ".$request->getBody()."\n-------------------\n";
        // });

        // $stack = HandlerStack::create();
        // $stack->push(Middleware::mapResponse(function ($response) {
        //     echo "\n+++++++++++++++++\nRESP HEADERS : ".print_r($response->getHeaders(), true)."\n+++++++++++++++++++\n";
        //     echo "\n------------------\nRESP BODY : ".$response->getBody()."\n-------------------\n";
        //     return $response;
        // }));

        // $this->httpClient = new Client(['debug' => true, 'handler' => $tapMiddleware($stack)]);
        $this->httpClient = new Client();

    }

    public function tearDown() {
        foreach($this->filesToDelete as $ftd) {
            unlink($ftd);
        }

        //$this->httpClient->delete("repositories/$this->rdf4jRepository");
        parent::tearDown();
    }


    /**
     * Test Pagination with DSA key.
     *
     * @return void
     */
    public function testPaginateDSA()
    {
        $handleClient = new HandleClient('file://'.$this->dsaTmpPath, $this->dsaPemPassword, $this->dsaAdminHandle, $this->handleHost, $this->handlePort, $this->httpClient);

        $pagination = $handleClient->paginateAll($this->testPrefix);

        $this->assertNotNull($pagination);

        $this->assertInstanceOf("Illuminate\Pagination\LengthAwarePaginator", $pagination, "Must be a LengthAwarePaginator");

        $this->assertGreaterThanOrEqual(1, $pagination->count(), "Must have at least 1 handle");
        $this->assertGreaterThanOrEqual(1, $pagination->total(), "Total is at least 1");

    }


    /**
     * Test Pagination with RSA key.
     *
     * @return void
     */
    public function testPaginateRSA()
    {
        $handleClient = new HandleClient('file://'.$this->rsaTmpPath, $this->rsaPemPassword, $this->rsaAdminHandle, $this->handleHost, $this->handlePort, $this->httpClient);

        $pagination = $handleClient->paginateAll($this->testPrefix);

        $this->assertNotNull($pagination);

        $this->assertInstanceOf("Illuminate\Pagination\LengthAwarePaginator", $pagination, "Must be a LengthAwarePaginator");

        $this->assertGreaterThanOrEqual(1, $pagination->count(), "Must have at least 1 handle");
        $this->assertGreaterThanOrEqual(1, $pagination->total(), "Total is at least 1");

    }

    /**
     * Test Pagination with Client Certificate.
     *
     * @return void
     */
    public function testPaginateCert()
    {
        $handleClient = new HandleClient($this->certTmpPath, $this->certPemPassword, $this->certAdminHandle, $this->handleHost, $this->handlePort, $this->httpClient);

        $pagination = $handleClient->paginateAll($this->testPrefix);

        $this->assertNotNull($pagination);

        $this->assertInstanceOf("Illuminate\Pagination\LengthAwarePaginator", $pagination, "Must be a LengthAwarePaginator");

        $this->assertGreaterThanOrEqual(1, $pagination->count(), "Must have at least 1 handle");
        $this->assertGreaterThanOrEqual(1, $pagination->total(), "Total is at least 1");

    }


    /**
     * Test Handle creation
     */
    public function testCreateHandleUrl() {

        $handleClient = new HandleClient('file://'.$this->rsaTmpPath, $this->rsaPemPassword, $this->rsaAdminHandle, $this->handleHost, $this->handlePort, $this->httpClient);

        $pagination = $handleClient->paginateAll($this->testPrefix);
        $totalPrev = $pagination->total();

        $handle = strtoupper(uniqid("$this->testPrefix/TEST_HANDLE_CLIENT_"));

        //$handle = "$this->testPrefix/TEST_HANDLE_CLIENT_";

        $handleClient->createHandleUrlRecord($handle, "http://www.example.com");

        $pagination = $handleClient->paginateAll($this->testPrefix);

        $this->assertEquals($totalPrev + 1, $pagination->total(), "Must have one more handle");

        $this->assertContains($handle, $pagination);

        $handleClient->deleteHandle($handle);

    }

    /**
     * Test Handle delete
     */
    public function testDeleteHandle() {

        $handleClient = new HandleClient('file://'.$this->rsaTmpPath, $this->rsaPemPassword, $this->rsaAdminHandle, $this->handleHost, $this->handlePort, $this->httpClient);

        $pagination = $handleClient->paginateAll($this->testPrefix);
        $totalPrev = $pagination->total();

        $handle = strtoupper(uniqid("$this->testPrefix/TEST_HANDLE_CLIENT_"));

        $handleClient->createHandleUrlRecord($handle, "http://www.example.com");
        $handleClient->deleteHandle($handle);


        $pagination = $handleClient->paginateAll($this->testPrefix);

        $this->assertEquals($totalPrev, $pagination->total(), "Must have one more handle");

        $this->assertNotContains($handle, $pagination);


    }

}
