using System;
using System.Diagnostics;
using System.IO;

namespace FrymasterBadgeApp;

public static class AppLogger
{
    private static readonly string LogDirectory = Environment.GetFolderPath(
        Environment.SpecialFolder.LocalApplicationData
    );
    private static readonly string BaseLogName = "FrymasterBadgeApp";
    private static readonly long MaxFileSizeBytes = 5 * 1024 * 1024; // 5MB
    private static readonly object _lock = new();

    static AppLogger()
    {
        Log("DEBUG", "AppLogger initialized");
    }

    private static string GetCurrentLogPath()
    {
        string date = DateTime.Now.ToString("yyyy-MM-dd");
        return Path.Combine(LogDirectory, $"{BaseLogName}_{date}.log");
    }

    public static void Info(string message) => Log("INFO", message);

    public static void Warn(string message) => Log("WARN", message);

    public static void Warning(string message) => Log("WARNING", message);

    /// <summary>
    /// Logs an error to the application log, including the given message.
    /// <param name="message">The message to be logged.</param name="ex">The exception associated with the error, or null if none.</summary>
    public static void Error(string message, Exception? ex = null)
    {
        string full = ex != null ? $"{message}\nException: {ex}" : message;
        Log("ERROR", full);
    }

    /// <summary>
    /// Logs a a instructions to the application log, including the given message.
    /// <param name="message">The message to be logged.</summary>
    public static void Debug(string message)
    {
#if DEBUG
        Log("DEBUG", message);
#endif
    }

    /// <summary>
    /// Logs a message to the application log, including the given message.
    /// </summary>
    private static void Log(string level, string message)
    {
        string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
        string logLine = $"[{timestamp}] [{level}] {message}";

        lock (_lock)
        {
            string logPath = GetCurrentLogPath();

            // Rotate if too large
            if (File.Exists(logPath) && new FileInfo(logPath).Length > MaxFileSizeBytes)
            {
                string backup = logPath + ".old";
                if (File.Exists(backup))
                    File.Delete(backup);
                File.Move(logPath, backup);
            }

            try
            {
                File.AppendAllText(logPath, logLine + Environment.NewLine);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Log file write failed: {ex.Message}");
            }

            Console.WriteLine(logLine);
            System.Diagnostics.Debug.WriteLine(logLine);
        }
    }

    /// <summary>
    /// Deletes old log files that are older than the given number of days.
    /// </summary>
    public static void CleanupOldLogs(int daysToKeep = 30)
    {
        var cutoff = DateTime.Now.AddDays(-daysToKeep);
        foreach (var file in Directory.GetFiles(LogDirectory, $"{BaseLogName}_*.log"))
        {
            if (File.GetCreationTime(file) < cutoff)
            {
                try
                {
                    File.Delete(file);
                }
                catch { }
            }
        }
    }
}
