namespace RolemasterDb.ImportTool;

public sealed class CriticalSourceImageArtifactRegenerator(PdfXmlExtractor pdfXmlExtractor)
{
    public async Task GenerateAsync(
        string pdfPath,
        ImportArtifactPaths artifactPaths,
        IReadOnlyList<CriticalImageArtifactMetadata> imageArtifacts,
        CancellationToken cancellationToken = default)
    {
        if (imageArtifacts.Count == 0)
        {
            throw new InvalidOperationException("No image artifact metadata was supplied.");
        }

        Directory.CreateDirectory(artifactPaths.PagesDirectoryPath);
        Directory.CreateDirectory(artifactPaths.CellsDirectoryPath);

        var renderProfiles = imageArtifacts
            .Select(item => (item.Crop.RenderDpi, item.Crop.ScaleFactor))
            .Distinct()
            .ToList();
        if (renderProfiles.Count != 1)
        {
            throw new InvalidOperationException("Image artifact metadata contains inconsistent render settings.");
        }

        var renderDpi = renderProfiles[0].RenderDpi;
        foreach (var pageNumber in imageArtifacts
                     .Select(item => item.Crop.PageNumber)
                     .Distinct()
                     .OrderBy(item => item))
        {
            await pdfXmlExtractor.RenderPagePngAsync(
                pdfPath,
                pageNumber,
                artifactPaths.GetPageImagePath(pageNumber),
                renderDpi,
                cancellationToken);
        }

        foreach (var imageArtifact in imageArtifacts)
        {
            var crop = imageArtifact.Crop;
            var fullPath = artifactPaths.ResolveRelativePath(imageArtifact.RelativePath);
            Directory.CreateDirectory(Path.GetDirectoryName(fullPath)!);

            await pdfXmlExtractor.RenderCropPngAsync(
                pdfPath,
                crop.PageNumber,
                crop.CropLeft,
                crop.CropTop,
                crop.CropWidth,
                crop.CropHeight,
                fullPath,
                crop.RenderDpi,
                cancellationToken);
        }
    }
}