<?php

namespace App\Services\Integrations\CloudAssets;

use App\Models\ApiCredential;
use Aws\Credentials\Credentials;
use Aws\Ec2\Ec2Client;
use Aws\Rds\RdsClient;
use Aws\S3\S3Client;
use Exception;
use Illuminate\Support\Facades\Log;

class AwsIntegration
{
    /**
    * Retrieve the credentials for accessing AWS services.
    */
    public function getCredentials()
    {
        return ApiCredential::where('slug', 'aws_cloud_assets')->first();
    }

    /**
     * Generates the credentials for API using Credentials class.
     */
    public function generateAwsCredentials()
    {
        $ApiCredentials = $this->getCredentials();

        return new Credentials($ApiCredentials?->user_name, $ApiCredentials?->password);
    }

    /**
     * checkApiConnection function.
     *
     * @throws Exception description of exception
     * @return int
     */
    public function checkApiConnection()
    {
        try {
            $awsCredentials = $this->generateAwsCredentials();
            $ec2Client = new Ec2Client([
                'region' => 'us-east-2',
                'version' => 'latest',
                'credentials' => $awsCredentials
            ]);

            $ec2Client->describeInstances();

            return 1;
        } catch (Exception $e) {
            return 0;
        }
    }

    /**
     * Retrieves instances from the specified region using the provided credentials.
     *
     * @param string $region The region from which to retrieve instances
     * @throws Exception description of exception
     * @return mixed The retrieved instances, or false if an exception occurs
     */
    public function getInstances($region)
    {
        try {
            $awsCredentials = $this->generateAwsCredentials();
            $ec2Client = new Ec2Client([
                'region' => $region,
                'version' => 'latest',
                'credentials' => $awsCredentials
            ]);

            return $ec2Client->describeInstances();
        } catch (Exception $e) {
            return false;
        }
    }

    /**
     * Get the list of Amazon S3 buckets in the specified region.
     *
     * @param string $region The region to retrieve the buckets from.
     * @throws Exception If an error occurs while retrieving the buckets.
     * @return mixed An array of bucket information or false if an error occurs.
     */
    public function getS3Buckets(string $region)
    {
        try {
            $awsCredentials = $this->generateAwsCredentials();
            $s3Client = new S3Client([
                'region' => $region,
                'version' => 'latest',
                'credentials' => $awsCredentials
            ]);

            return $s3Client->listBuckets();
        } catch (Exception $e) {
            Log::error($e->getMessage());

            return false;
        }
    }

    /**
     * Retrieves the location of the specified S3 bucket in the given region.
     *
     * @param string $bucketName The name of the S3 bucket
     * @param string $region The region where the S3 bucket is located
     * @throws Exception
     * @return string The region where the S3 bucket is located
     */
    public function getS3BucketLocation(string $bucketName, string $region): string
    {
        try {
            $awsCredentials = $this->generateAwsCredentials();
            $s3Client = new S3Client([
                'region' => $region,
                'version' => 'latest',
                'credentials' => $awsCredentials
            ]);
            $bucketLocation = $s3Client->getBucketLocation(['Bucket' => $bucketName]);
            $region = $bucketLocation->get('LocationConstraint') ?? '';

            return $region;
        } catch (Exception $e) {
            Log::error($e->getMessage());

            return '';
        }
    }

    /**
     * Retrieves the RDS instances in the specified region.
     *
     * @param string $region The region where the RDS instances are located.
     * @throws Exception When an error occurs while retrieving the RDS instances.
     * @return mixed The list of RDS instances or false if an error occurs.
     */
    public function getRds(string $region)
    {
        try {
            $awsCredentials = $this->generateAwsCredentials();
            $rdsClient = new RdsClient([
                'region' => $region,
                'version' => 'latest',
                'credentials' => $awsCredentials
            ]);

            return $rdsClient->describeDBInstances();
        } catch (Exception $e) {
            Log::error($e->getMessage());

            return false;
        }
    }
}