using System.Net;
using System.Text;

namespace SatelliteProvider.IntegrationTests;

public static class SecurityTests
{
    public static async Task RunAll(HttpClient httpClient)
    {
        RouteTestHelpers.PrintTestHeader("Test: Security (SEC-01..SEC-04)");

        await Sec01_SqlInjectionViaCoordinates(httpClient);
        await Sec02_PathTraversalInTileServing(httpClient);
        await Sec03_OversizedRegionRequest(httpClient);
        await Sec04_MalformedJson(httpClient);

        Console.WriteLine("✓ Security Tests: PASSED");
    }

    private static async Task Sec01_SqlInjectionViaCoordinates(HttpClient httpClient)
    {
        Console.WriteLine();
        Console.WriteLine("SEC-01: SQL injection attempt in coordinate query string");

        var injection = "' OR 1=1 --";
        var url = $"/api/satellite/tiles/latlon?lat={Uri.EscapeDataString(injection)}&lon=37.647063&zoom=18";
        var response = await httpClient.GetAsync(url);

        if (response.StatusCode != HttpStatusCode.BadRequest && response.StatusCode != HttpStatusCode.UnprocessableEntity)
        {
            throw new Exception($"SEC-01 expected 400/422 for non-numeric coordinate, got {(int)response.StatusCode}");
        }

        Console.WriteLine($"  ✓ Non-numeric coordinate rejected with HTTP {(int)response.StatusCode}");
    }

    private static async Task Sec02_PathTraversalInTileServing(HttpClient httpClient)
    {
        Console.WriteLine();
        Console.WriteLine("SEC-02: Path traversal attempt against tile serving endpoint");

        var traversalPaths = new[]
        {
            "/tiles/../../etc/passwd",
            "/tiles/18/..%2F..%2Fetc%2Fpasswd/0",
            "/tiles/18/0/..%2F..%2Fetc%2Fpasswd"
        };

        foreach (var path in traversalPaths)
        {
            var response = await httpClient.GetAsync(path);
            var status = (int)response.StatusCode;

            if (status == 200)
            {
                throw new Exception($"SEC-02 expected non-200 for traversal '{path}', got 200");
            }

            Console.WriteLine($"  ✓ Traversal '{path}' rejected with HTTP {status}");
        }
    }

    private static async Task Sec03_OversizedRegionRequest(HttpClient httpClient)
    {
        Console.WriteLine();
        Console.WriteLine("SEC-03: Oversized region request (sizeMeters beyond allowed cap)");

        var regionId = Guid.NewGuid();
        var body = $"{{\"id\":\"{regionId}\",\"lat\":47.461747,\"lon\":37.647063,\"sizeMeters\":1000000,\"zoomLevel\":18,\"stitchTiles\":false}}";
        var content = new StringContent(body, Encoding.UTF8, "application/json");
        var response = await httpClient.PostAsync("/api/satellite/request", content);
        var status = (int)response.StatusCode;

        if (status != 400 && status != 422)
        {
            throw new Exception($"SEC-03 expected 400/422 for oversized region (1,000,000m), got {status}");
        }

        Console.WriteLine($"  ✓ Oversized region rejected with HTTP {status}");
    }

    private static async Task Sec04_MalformedJson(HttpClient httpClient)
    {
        Console.WriteLine();
        Console.WriteLine("SEC-04: Malformed JSON body");

        var malformed = "{ this is not json ::";
        var content = new StringContent(malformed, Encoding.UTF8, "application/json");
        var response = await httpClient.PostAsync("/api/satellite/request", content);
        var status = (int)response.StatusCode;

        if (status != 400 && status != 415 && status != 422)
        {
            throw new Exception($"SEC-04 expected 400/415/422 for malformed JSON, got {status}");
        }

        Console.WriteLine($"  ✓ Malformed JSON rejected with HTTP {status}");
    }
}
