using Health.Application.Diets;

namespace Health.Infrastructure.Diets;

public sealed class DietImageAnalysisCoordinator(IDietImageAnalysisQueue queue) : IDietImageAnalysisCoordinator
{
    private const long MaxImageBytes = 20 * 1024 * 1024;
    private static readonly HashSet<string> AllowedExtensions = new(StringComparer.OrdinalIgnoreCase)
    {
        ".jpg", ".jpeg", ".png", ".heic"
    };

    private readonly IDietImageAnalysisQueue _queue = queue;

    public async Task<DietImageAnalysisResult> AnalyzeAsync(IReadOnlyList<DietImageUploadFile> files, CancellationToken ct)
    {
        if (files.Count == 0)
            return new DietImageAnalysisResult(false, 40001, null, "请上传至少一张图片");

        var uploadsDir = Path.Combine(Directory.GetCurrentDirectory(), "uploads", "diet-analysis");
        Directory.CreateDirectory(uploadsDir);
        var paths = new List<string>();
        var handedOff = false;

        try
        {
            foreach (var file in files)
            {
                if (file.Length <= 0 || file.Length > MaxImageBytes)
                    return new DietImageAnalysisResult(false, 40001, null, "文件大小超过 20MB 限制");

                var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
                if (!AllowedExtensions.Contains(extension))
                    return new DietImageAnalysisResult(false, 40001, null, "不支持的图片格式，仅支持 JPG/PNG/HEIC");

                var filePath = Path.Combine(uploadsDir, $"{Guid.NewGuid()}{extension}");
                await using var stream = new FileStream(filePath, FileMode.CreateNew);
                await file.Content.CopyToAsync(stream, ct);
                paths.Add(filePath);
            }

            var jobId = await _queue.EnqueueAsync(paths, ct);
            handedOff = true;
            return await _queue.WaitForResultAsync(jobId, ct);
        }
        catch
        {
            if (!handedOff)
            {
                foreach (var path in paths)
                {
                    try { if (File.Exists(path)) File.Delete(path); }
                    catch (IOException) { }
                    catch (UnauthorizedAccessException) { }
                }
            }
            throw;
        }
    }
}
