using System.IO.Compression;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using SatelliteProvider.Common.Configs;
using SatelliteProvider.Services.RouteManagement;

namespace SatelliteProvider.Tests;

// AZ-364 / C11: zip builder carries the entry-name resolution logic
// (relative-to-tiles-dir vs. fall-back to file name) and the
// missing-file-tolerant scan loop.
public class TilesZipBuilderTests : IDisposable
{
    private readonly string _readyDir;
    private readonly string _tilesDir;

    public TilesZipBuilderTests()
    {
        var root = Path.Combine(Path.GetTempPath(), "az364_zip_" + Guid.NewGuid().ToString("N"));
        _readyDir = Path.Combine(root, "ready");
        _tilesDir = Path.Combine(root, "tiles");
        Directory.CreateDirectory(_readyDir);
        Directory.CreateDirectory(_tilesDir);
    }

    public void Dispose()
    {
        var root = Path.GetDirectoryName(_readyDir)!;
        if (Directory.Exists(root))
        {
            Directory.Delete(root, recursive: true);
        }
        GC.SuppressFinalize(this);
    }

    [Fact]
    public async Task BuildAsync_AddsEntriesUnderTilesPrefixAndSkipsMissing_AZ364_AC1()
    {
        // Arrange
        var storageOptions = Options.Create(new StorageConfig
        {
            ReadyDirectory = _readyDir,
            TilesDirectory = _tilesDir,
        });
        var sut = new TilesZipBuilder(storageOptions, NullLogger<TilesZipBuilder>.Instance);

        var subdir = Path.Combine(_tilesDir, "18", "1", "2");
        Directory.CreateDirectory(subdir);
        var realTile = Path.Combine(subdir, "tile_18_1234_5678_1700000000.jpg");
        await File.WriteAllBytesAsync(realTile, new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 });

        var routeId = Guid.NewGuid();
        var tiles = new List<TileInfo>
        {
            new(40.0, -73.0, realTile),
            new(41.0, -74.0, Path.Combine(_tilesDir, "missing_tile.jpg")),
        };

        // Act
        var zipPath = await sut.BuildAsync(routeId, tiles);

        // Assert
        zipPath.Should().Be(Path.Combine(_readyDir, $"route_{routeId}_tiles.zip"));
        File.Exists(zipPath).Should().BeTrue();

        using var archive = ZipFile.OpenRead(zipPath);
        archive.Entries.Should().HaveCount(1);
        archive.Entries.Single().FullName.Should().Be("tiles/18/1/2/tile_18_1234_5678_1700000000.jpg");
    }
}
