<?php

namespace VendorDuplicator\Aws\Script\Composer;

use VendorDuplicator\Composer\Script\Event;
use VendorDuplicator\Symfony\Component\Filesystem\Exception\IOException;
use VendorDuplicator\Symfony\Component\Filesystem\Filesystem;
class Composer
{
    public static function removeUnusedServicesInDev(Event $event, ?Filesystem $filesystem = null)
    {
        self::removeUnusedServicesWithConfig($event, $filesystem, \true);
    }
    public static function removeUnusedServices(Event $event, ?Filesystem $filesystem = null)
    {
        self::removeUnusedServicesWithConfig($event, $filesystem, \false);
    }
    private static function removeUnusedServicesWithConfig(Event $event, ?Filesystem $filesystem = null, $isDev = \false)
    {
        if ($isDev && !$event->isDevMode()) {
            return;
        }
        $composer = $event->getComposer();
        $extra = $composer->getPackage()->getExtra();
        $listedServices = isset($extra['aws/aws-sdk-php']) ? $extra['aws/aws-sdk-php'] : [];
        if ($listedServices) {
            $serviceMapping = self::buildServiceMapping();
            self::verifyListedServices($serviceMapping, $listedServices);
            $filesystem = $filesystem ?: new Filesystem();
            $vendorPath = $composer->getConfig()->get('vendor-dir');
            self::removeServiceDirs($event, $filesystem, $serviceMapping, $listedServices, $vendorPath);
        } else {
            throw new \InvalidArgumentException('There are no services listed. Did you intend to use this script?');
        }
    }
    public static function buildServiceMapping()
    {
        $serviceMapping = [];
        $manifest = require __DIR__ . '/../../data/manifest.json.php';
        foreach ($manifest as $service => $attributes) {
            $serviceMapping[$attributes['namespace']] = $service;
        }
        return $serviceMapping;
    }
    private static function verifyListedServices($serviceMapping, $listedServices)
    {
        foreach ($listedServices as $serviceToKeep) {
            if (!isset($serviceMapping[$serviceToKeep])) {
                throw new \InvalidArgumentException("'{$serviceToKeep}' is not a valid AWS service namespace. Please check spelling and casing.");
            }
        }
    }
    private static function removeServiceDirs($event, $filesystem, $serviceMapping, $listedServices, $vendorPath)
    {
        $unsafeForDeletion = ['Kms', 'S3', 'SSO', 'SSOOIDC', 'Sts'];
        if (in_array('DynamoDbStreams', $listedServices)) {
            $unsafeForDeletion[] = 'DynamoDb';
        }
        $clientPath = $vendorPath . '/aws/aws-sdk-php/src/';
        $modelPath = $clientPath . 'data/';
        $deleteCount = 0;
        foreach ($serviceMapping as $clientName => $modelName) {
            if (!in_array($clientName, $listedServices) && !in_array($clientName, $unsafeForDeletion)) {
                $clientDir = $clientPath . $clientName;
                $modelDir = $modelPath . $modelName;
                if ($filesystem->exists([$clientDir, $modelDir])) {
                    $attempts = 3;
                    $delay = 2;
                    while ($attempts) {
                        try {
                            $filesystem->remove([$clientDir, $modelDir]);
                            $deleteCount++;
                            break;
                        } catch (IOException $e) {
                            $attempts--;
                            if (!$attempts) {
                                throw new IOException("Removal failed after several attempts. Last error: " . $e->getMessage());
                            } else {
                                sleep($delay);
                                $event->getIO()->write("Error encountered: " . $e->getMessage() . ". Retrying...");
                                $delay += 2;
                            }
                        }
                    }
                }
            }
        }
        $event->getIO()->write("Removed {$deleteCount} AWS service" . ($deleteCount === 1 ? '' : 's'));
    }
}
