using SatelliteProvider.TestSupport;

namespace SatelliteProvider.IntegrationTests;

class Program
{
    static async Task<int> Main(string[] args)
    {
        var apiUrl = Environment.GetEnvironmentVariable("API_URL") ?? "http://api:8080";
        var modeEnv = Environment.GetEnvironmentVariable("INTEGRATION_TESTS_MODE")?.Trim().ToLowerInvariant();
        var modeArg = args.FirstOrDefault(a => a.Equals("--smoke", StringComparison.OrdinalIgnoreCase) || a.Equals("--full", StringComparison.OrdinalIgnoreCase));

        if (modeArg != null)
        {
            TestRunMode.Smoke = modeArg.Equals("--smoke", StringComparison.OrdinalIgnoreCase);
        }
        else if (!string.IsNullOrEmpty(modeEnv))
        {
            TestRunMode.Smoke = modeEnv == "smoke";
        }

        string jwtSecret;
        try
        {
            jwtSecret = JwtTestHelpers.ResolveSecretOrThrow();
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine("❌ Integration tests cannot start without a valid JWT secret.");
            Console.WriteLine($"   {ex.Message}");
            return 1;
        }

        Console.WriteLine("Starting Integration Tests");
        Console.WriteLine("=========================");
        Console.WriteLine($"API URL : {apiUrl}");
        Console.WriteLine($"Mode    : {(TestRunMode.Smoke ? "smoke (fast subset, tightened timeouts)" : "full")}");
        Console.WriteLine($"Auth    : JWT_SECRET resolved ({System.Text.Encoding.UTF8.GetByteCount(jwtSecret)} bytes)");
        Console.WriteLine();

        using var httpClient = new HttpClient
        {
            BaseAddress = new Uri(apiUrl),
            Timeout = TimeSpan.FromMinutes(15)
        };

        var defaultToken = JwtTokenFactory.Create(jwtSecret, JwtTestHelpers.DefaultSubject);
        JwtTestHelpers.AttachDefaultAuthorization(httpClient, defaultToken);

        try
        {
            Console.WriteLine("Waiting for API to be ready...");
            await WaitForApiReady(httpClient);
            Console.WriteLine("✓ API is ready");
            Console.WriteLine();

            await JwtIntegrationTests.RunAll(apiUrl, jwtSecret);
            await UavUploadTests.RunAll(apiUrl, jwtSecret);

            if (TestRunMode.Smoke)
            {
                await RunSmokeSuite(httpClient);
            }
            else
            {
                await RunFullSuite(httpClient);
            }

            Console.WriteLine();
            Console.WriteLine("=========================");
            Console.WriteLine("All tests completed successfully!");
            return 0;
        }
        catch (Exception ex)
        {
            Console.WriteLine();
            Console.WriteLine("❌ Integration tests failed");
            Console.WriteLine($"Error: {ex.Message}");
            Console.WriteLine($"Stack trace: {ex.StackTrace}");
            return 1;
        }
    }

    static async Task RunSmokeSuite(HttpClient httpClient)
    {
        await TileTests.RunGetTileByLatLonTest(httpClient);
        await RegionTests.RunRegionProcessingTest_200m_Zoom18(httpClient);
        await BasicRouteTests.RunSimpleRouteTest(httpClient);
        await ExtendedRouteTests.RunRouteWithTilesZipTest(httpClient);
        await SecurityTests.RunAll(httpClient);
        await StubAndErrorContractTests.RunAll(httpClient);
        await IdempotentPostTests.RunAll(httpClient);
        await MigrationTests.RunAll();
    }

    static async Task RunFullSuite(HttpClient httpClient)
    {
        await TileTests.RunGetTileByLatLonTest(httpClient);

        await RegionTests.RunRegionProcessingTest_200m_Zoom18(httpClient);
        await RegionTests.RunRegionProcessingTest_400m_Zoom17(httpClient);
        await RegionTests.RunRegionProcessingTest_500m_Zoom18(httpClient);

        await BasicRouteTests.RunSimpleRouteTest(httpClient);
        await BasicRouteTests.RunRouteWithRegionProcessingAndStitching(httpClient);
        await ExtendedRouteTests.RunRouteWithTilesZipTest(httpClient);
        await ComplexRouteTests.RunComplexRouteWithStitching(httpClient);
        await ComplexRouteTests.RunComplexRouteWithStitchingAndGeofences(httpClient);
        await ExtendedRouteTests.RunExtendedRouteEast(httpClient);

        await SecurityTests.RunAll(httpClient);
        await StubAndErrorContractTests.RunAll(httpClient);
        await IdempotentPostTests.RunAll(httpClient);
        await MigrationTests.RunAll();
    }

    static async Task WaitForApiReady(HttpClient httpClient, int maxRetries = 30)
    {
        for (int i = 0; i < maxRetries; i++)
        {
            try
            {
                var response = await httpClient.GetAsync("/");
                if (response.IsSuccessStatusCode || response.StatusCode == System.Net.HttpStatusCode.NotFound)
                {
                    return;
                }
            }
            catch
            {
            }

            Console.WriteLine($"  Attempt {i + 1}/{maxRetries} - waiting 2 seconds...");
            await Task.Delay(2000);
        }

        throw new Exception("API did not become ready in time");
    }
}
