using System;
using System.IO;
using System.Text;

namespace AutoIngest.Core
{
    /// <summary>
    /// A minimal append-only, rolling text-file logger. The on-screen toast log vanishes on
    /// restart; this mirrors every line to disk so a "my photos disappeared" report is diagnosable
    /// after the fact. Lives at <c>%LocalAppData%\AutoIngest\autoingest.log</c> (per-user, does
    /// not roam). Rolls to a single <c>.bak</c> at ~1 MB so it never grows unbounded.
    ///
    /// Thread-safe: the import coordinator raises log events on its background thread; the file
    /// is written under a lock so concurrent appends serialize cleanly.
    /// </summary>
    public static class FileLogger
    {
        static readonly string LogDir = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
            "AutoIngest");

        public static string LogPath => Path.Combine(LogDir, "autoingest.log");
        static string BakPath => Path.Combine(LogDir, "autoingest.log.bak");

        const long MaxBytes = 1_048_576; // 1 MB — roll before the file gets unwieldy
        static readonly object _lock = new();

        /// <summary>
        /// Appends one timestamped line. Best-effort: a log-write failure (full disk, locked file)
        /// is swallowed — the logger must never throw into its caller, especially not into the
        /// import pipeline.
        /// </summary>
        public static void Log(string message)
        {
            try
            {
                lock (_lock)
                {
                    Directory.CreateDirectory(LogDir);
                    RollIfNeeded();
                    File.AppendAllText(LogPath,
                        $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}{Environment.NewLine}",
                        Encoding.UTF8);
                }
            }
            catch (UnauthorizedAccessException) { }
            catch (IOException) { }
        }

        /// <summary>Logs an exception with its type and stack trace, for unhandled-exception handlers.</summary>
        public static void LogException(string context, Exception ex)
            => Log($"{context}: {ex.GetType().Name}: {ex.Message}{Environment.NewLine}{ex.StackTrace}");

        /// <summary>
        /// Renames the current log to .bak (overwriting any prior .bak) once it crosses the size
        /// threshold. The directory therefore holds at most two log files: the active one and one
        /// backup — bounded disk use, predictable rotation.
        /// </summary>
        static void RollIfNeeded()
        {
            try
            {
                if (!File.Exists(LogPath)) return;
                if (new FileInfo(LogPath).Length < MaxBytes) return;
                if (File.Exists(BakPath)) File.Delete(BakPath);
                File.Move(LogPath, BakPath);
            }
            catch (UnauthorizedAccessException) { }
            catch (IOException) { }
        }
    }
}
