using System;
using System.Collections.ObjectModel;
using System.IO;
using Tornado3_2026Election.Domain;

namespace Tornado3_2026Election.Services;

public sealed class LogService
{
    private const int MaxEntries = 400;
    private const long MaxDebugLogBytes = 2 * 1024 * 1024;
    private static readonly object FileSync = new();
    private static readonly string DebugLogPath = Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
        "Tornado3_2026Election",
        "debug.log");

    public ObservableCollection<LogEntry> Entries { get; } = [];

    public void Info(string message) => Add(LogLevel.Info, message);

    public void Warning(string message) => Add(LogLevel.Warning, message);

    public void Error(string message) => Add(LogLevel.Error, message);

    public void Clear() => Common.UiDispatcher.Enqueue(Entries.Clear);

    private void Add(LogLevel level, string message)
    {
        WriteDebugLog(level, message);

        Common.UiDispatcher.Enqueue(() =>
        {
            Entries.Insert(0, new LogEntry
            {
                Timestamp = DateTimeOffset.Now,
                Level = level,
                Message = message
            });

            while (Entries.Count > MaxEntries)
            {
                Entries.RemoveAt(Entries.Count - 1);
            }
        });
    }

    private static void WriteDebugLog(LogLevel level, string message)
    {
        try
        {
            lock (FileSync)
            {
                var directory = Path.GetDirectoryName(DebugLogPath);
                if (!string.IsNullOrWhiteSpace(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                if (File.Exists(DebugLogPath) && new FileInfo(DebugLogPath).Length > MaxDebugLogBytes)
                {
                    File.Delete(DebugLogPath);
                }

                File.AppendAllText(
                    DebugLogPath,
                    $"{DateTimeOffset.Now:yyyy-MM-dd HH:mm:ss.fff zzz} [{level}] {message}{Environment.NewLine}");
            }
        }
        catch
        {
            // Logging must not affect live CG control.
        }
    }
}
