using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using CamBooth.App.Core.Logging;

namespace CamBooth.App.Features.PhotoPrismUpload;

/// <summary>
/// Verfolgt, welche Bilder zu PhotoPrism hochgeladen wurden, und persistiert den Status.
/// </summary>
public class PhotoPrismUploadTracker
{
    private readonly Logger _logger;
    private readonly string _trackerFilePath;
    private Dictionary<string, UploadedImageInfo> _uploadedImages;

    private static readonly JsonSerializerOptions PrettyJson = new() { WriteIndented = true };

    public PhotoPrismUploadTracker(Logger logger, string trackerDirectory = "")
    {
        _logger = logger;

        var dir = ResolveDirectory(trackerDirectory);
        Directory.CreateDirectory(dir);

        _trackerFilePath = Path.Combine(dir, "photoprism_upload_history.json");
        _uploadedImages = new Dictionary<string, UploadedImageInfo>();

        LoadFromDisk();
    }

    // =========================================================================
    // Public API
    // =========================================================================

    /// <summary>
    /// Markiert ein Bild als erfolgreich hochgeladen.
    /// </summary>
    public void MarkAsUploaded(string filePath, string? photoId = null)
    {
        var key = GetKey(filePath);

        _uploadedImages[key] = new UploadedImageInfo
        {
            FileName = key,
            UploadedAt = DateTime.UtcNow,
            PhotoId = photoId,
            IsUploaded = true,
            RetryCount = 0,
            ErrorMessage = null
        };

        SaveToDisk();
        _logger.Debug($"Bild als hochgeladen markiert: {key}");
    }

    /// <summary>
    /// Markiert einen fehlgeschlagenen Upload-Versuch.
    /// </summary>
    public void MarkAsFailedUpload(string filePath, string? errorMessage = null)
    {
        var key = GetKey(filePath);

        if (_uploadedImages.TryGetValue(key, out var existing))
        {
            existing.RetryCount++;
            existing.LastRetryAt = DateTime.UtcNow;
            existing.ErrorMessage = errorMessage;
        }
        else
        {
            _uploadedImages[key] = new UploadedImageInfo
            {
                FileName = key,
                IsUploaded = false,
                RetryCount = 1,
                LastRetryAt = DateTime.UtcNow,
                ErrorMessage = errorMessage
            };
        }

        SaveToDisk();
        _logger.Warning($"Upload-Fehler für {key}: {errorMessage}");
    }

    /// <summary>
    /// Gibt an, ob ein Bild bereits erfolgreich hochgeladen wurde.
    /// </summary>
    public bool IsUploaded(string filePath)
    {
        var key = GetKey(filePath);
        return _uploadedImages.TryGetValue(key, out var info) && info.IsUploaded;
    }

    /// <summary>
    /// Gibt alle Dateien zurück, die noch nicht erfolgreich hochgeladen wurden.
    /// </summary>
    public List<string> GetFailedUploads(string pictureDirectory)
    {
        if (!Directory.Exists(pictureDirectory))
            return new List<string>();

        try
        {
            return Directory
                .GetFiles(pictureDirectory, "img_*.jpg")
                .Where(f => !IsUploaded(f))
                .ToList();
        }
        catch (Exception ex)
        {
            _logger.Error($"Fehler beim Scannen von {pictureDirectory}: {ex.Message}");
            return new List<string>();
        }
    }

    // =========================================================================
    // Private Helpers
    // =========================================================================

    private void LoadFromDisk()
    {
        try
        {
            if (!File.Exists(_trackerFilePath)) return;

            var json = File.ReadAllText(_trackerFilePath);
            _uploadedImages = JsonSerializer.Deserialize<Dictionary<string, UploadedImageInfo>>(json)
                              ?? new Dictionary<string, UploadedImageInfo>();

            _logger.Info($"PhotoPrism Upload-History geladen: {_uploadedImages.Count} Einträge");
        }
        catch (Exception ex)
        {
            _logger.Error($"Fehler beim Laden der PhotoPrism Upload-History: {ex.Message}");
            _uploadedImages = new Dictionary<string, UploadedImageInfo>();
        }
    }

    private void SaveToDisk()
    {
        try
        {
            File.WriteAllText(_trackerFilePath, JsonSerializer.Serialize(_uploadedImages, PrettyJson));
        }
        catch (Exception ex)
        {
            _logger.Error($"Fehler beim Speichern der PhotoPrism Upload-History: {ex.Message}");
        }
    }

    private static string GetKey(string filePath) => Path.GetFileName(filePath);

    private static string ResolveDirectory(string path)
    {
        if (string.IsNullOrWhiteSpace(path))
            return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PhotoPrismUploadTracking");

        return Path.IsPathRooted(path)
            ? path
            : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path);
    }

    // =========================================================================
    // Nested Types
    // =========================================================================

    public class UploadedImageInfo
    {
        public string FileName { get; set; } = string.Empty;
        public bool IsUploaded { get; set; }
        public DateTime UploadedAt { get; set; }
        public string? PhotoId { get; set; }
        public int RetryCount { get; set; }
        public DateTime? LastRetryAt { get; set; }
        public string? ErrorMessage { get; set; }
    }
}
