<?php

namespace AsyncAws\SecretsManager\Tests\Integration;

use AsyncAws\Core\Credentials\Credentials;
use AsyncAws\Core\Test\TestCase;
use AsyncAws\SecretsManager\Enum\FilterNameStringType;
use AsyncAws\SecretsManager\Input\CreateSecretRequest;
use AsyncAws\SecretsManager\Input\DeleteSecretRequest;
use AsyncAws\SecretsManager\Input\GetSecretValueRequest;
use AsyncAws\SecretsManager\Input\ListSecretsRequest;
use AsyncAws\SecretsManager\Input\PutSecretValueRequest;
use AsyncAws\SecretsManager\Input\UpdateSecretRequest;
use AsyncAws\SecretsManager\SecretsManagerClient;
use AsyncAws\SecretsManager\ValueObject\Filter;
use AsyncAws\SecretsManager\ValueObject\Tag;

class SecretsManagerClientTest extends TestCase
{
    protected function tearDown(): void
    {
        parent::tearDown(); // TODO: Change the autogenerated stub
    }

    public function testCreateSecret(): void
    {
        $client = $this->getClient();
        $key = 'testCreateName';
        $input = new CreateSecretRequest([
            'Name' => $key,
            'Description' => 'Test description',
            'SecretString' => 'testSecretValue',
            'Tags' => [new Tag([
                'Key' => 'tag1',
                'Value' => 'tagValue',
            ])],
        ]);
        $result = $client->CreateSecret($input);

        $result->resolve();

        self::assertStringStartsWith('arn:aws:secretsmanager:us-east-1:000000000000:secret:' . $key . '-', $result->getARN());
        self::assertSame($key, $result->getName());
        self::assertStringMatchesFormat('%s-%s-%s-%s-%s', $result->getVersionId());
    }

    public function testDeleteSecret(): void
    {
        $client = $this->getClient();

        $key = 'testDeleteName';

        $client->CreateSecret([
            'Name' => $key,
            'SecretString' => 'testSecretValue',
        ])->resolve();

        $input = new DeleteSecretRequest([
            'SecretId' => $key,
            'RecoveryWindowInDays' => 7,
            'ForceDeleteWithoutRecovery' => false,
        ]);
        $result = $client->DeleteSecret($input);
        $result->resolve();

        self::assertStringStartsWith('arn:aws:secretsmanager:us-east-1:000000000000:secret:' . $key . '-', $result->getARN());
        self::assertSame($key, $result->getName());
        // self::assertTODO(expected, $result->getDeletionDate());
    }

    public function testGetSecretValue(): void
    {
        $client = $this->getClient();

        $key = 'testGetName';
        $value = 'testSecretValue';
        $client->CreateSecret([
            'Name' => $key,
            'SecretString' => 'testSecretValue',
        ])->resolve();

        $input = new GetSecretValueRequest([
            'SecretId' => $key,
        ]);
        $result = $client->GetSecretValue($input);
        $result->resolve();

        self::assertStringStartsWith('arn:aws:secretsmanager:us-east-1:000000000000:secret:' . $key . '-', $result->getARN());
        self::assertSame($key, $result->getName());
        self::assertStringMatchesFormat('%s-%s-%s-%s-%s', $result->getVersionId());
        self::assertSame($value, $result->getSecretString());
    }

    public function testListSecrets(): void
    {
        $client = $this->getClient();
        $client->CreateSecret([
            'Name' => 'key1',
            'SecretString' => 'testSecretValue',
        ])->resolve();
        $createResult = $client->CreateSecret([
            'Name' => 'search1',
            'SecretString' => 'testSecretValue',
        ]);
        $createResult->resolve();

        $input = new ListSecretsRequest([
            'Filters' => [new Filter([
                'Key' => FilterNameStringType::NAME,
                'Values' => ['search'],
            ])],
        ]);
        $result = $client->ListSecrets($input);
        $result->resolve();

        $entries = iterator_to_array($result->getIterator());
        self::assertCount(1, $entries);
        self::assertSame($createResult->getArn(), $entries[0]->getArn());
    }

    public function testPutSecretValue(): void
    {
        $client = $this->getClient();
        $key = 'testPutKey';
        $client->CreateSecret(['Name' => $key])->resolve();

        $input = new PutSecretValueRequest([
            'SecretId' => $key,
            'SecretString' => 'testPutSecret',
        ]);
        $result = $client->PutSecretValue($input);

        $result->resolve();

        self::assertStringStartsWith('arn:aws:secretsmanager:us-east-1:000000000000:secret:' . $key . '-', $result->getARN());
        self::assertSame($key, $result->getName());
        self::assertStringMatchesFormat('%s-%s-%s-%s-%s', $result->getVersionId());
    }

    public function testUpdateSecret(): void
    {
        $client = $this->getClient();
        $key = 'testUpdateKey';
        $createResult = $client->CreateSecret([
            'Name' => $key,
            'SecretString' => 'testSecretValue',
        ]);
        $createResult->resolve();

        $input = new UpdateSecretRequest([
            'SecretId' => $key,
            'SecretString' => 'newSecretValue',
        ]);
        $result = $client->UpdateSecret($input);
        $result->resolve();

        self::assertNotSame($createResult->getVersionId(), $result->getVersionId());
        self::assertSame($createResult->getArn(), $result->getArn());
    }

    private function getClient(): SecretsManagerClient
    {
        return new SecretsManagerClient([
            'endpoint' => 'http://localhost:4577',
        ], new Credentials('aws_id', 'aws_secret'));
    }
}
