using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Text;

namespace StandardScene.Signal.Logic
{
    /// <summary>
    /// 磁条交管放行留档，按车名分目录：log/mag-traffic/car{name}/release_yyyyMMdd.log
    /// 进程启停等写到 log/mag-traffic/_sys/sys_yyyyMMdd.log
    /// </summary>
    public static class MagTrafficFileLogger
    {
        private static readonly ConcurrentDictionary<string, object> CarLocks = new ConcurrentDictionary<string, object>(StringComparer.OrdinalIgnoreCase);
        private static readonly object SysLock = new object();
        private static readonly char[] InvalidNameChars = Path.GetInvalidFileNameChars();
        private static string _baseDirectory = "log";
        private static bool _enabled = true;

        public static void Configure(string baseDirectory, bool enabled)
        {
            _baseDirectory = string.IsNullOrWhiteSpace(baseDirectory) ? "log" : baseDirectory.Trim();
            _enabled = enabled;
        }

        public static string GetLogDirectory()
        {
            return Path.Combine(ResolveBaseDirectory(), "mag-traffic");
        }

        /// <summary>目录名 car{name}；名称为空时回退 car{id}。</summary>
        public static string GetCarFolderKey(string carName, int carId)
        {
            var safe = SanitizeName(carName);
            if (string.IsNullOrWhiteSpace(safe))
            {
                safe = carId > 0 ? carId.ToString() : "unknown";
            }

            return "car" + safe;
        }

        public static string GetCarLogDirectory(string carName, int carId = 0)
        {
            return Path.Combine(GetLogDirectory(), GetCarFolderKey(carName, carId));
        }

        public static string GetCurrentCarLogFilePath(string carName, int carId = 0)
        {
            return Path.Combine(GetCarLogDirectory(carName, carId), $"release_{DateTime.Now:yyyyMMdd}.log");
        }

        public static string GetCurrentSysLogFilePath()
        {
            return Path.Combine(GetLogDirectory(), "_sys", $"sys_{DateTime.Now:yyyyMMdd}.log");
        }

        /// <summary>按车名写入放行记录。</summary>
        public static void Write(string carName, int carId, string message)
        {
            if (!_enabled || string.IsNullOrWhiteSpace(message))
            {
                return;
            }

            var folderKey = GetCarFolderKey(carName, carId);
            var carLock = CarLocks.GetOrAdd(folderKey, _ => new object());
            lock (carLock)
            {
                try
                {
                    var directory = Path.Combine(GetLogDirectory(), folderKey);
                    Directory.CreateDirectory(directory);
                    var path = Path.Combine(directory, $"release_{DateTime.Now:yyyyMMdd}.log");
                    File.AppendAllText(
                        path,
                        $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {message}{Environment.NewLine}",
                        new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
                }
                catch
                {
                }
            }
        }

        /// <summary>进程启停、重载配置等非单车事件。</summary>
        public static void WriteSystem(string message)
        {
            if (!_enabled || string.IsNullOrWhiteSpace(message))
            {
                return;
            }

            lock (SysLock)
            {
                try
                {
                    var path = GetCurrentSysLogFilePath();
                    Directory.CreateDirectory(Path.GetDirectoryName(path) ?? GetLogDirectory());
                    File.AppendAllText(
                        path,
                        $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {message}{Environment.NewLine}",
                        new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
                }
                catch
                {
                }
            }
        }

        private static string SanitizeName(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                return "";
            }

            var chars = name.Trim().Select(ch => InvalidNameChars.Contains(ch) || ch <= 31 ? '_' : ch).ToArray();
            var safe = new string(chars).Trim('.', ' ');
            while (safe.Contains("__"))
            {
                safe = safe.Replace("__", "_");
            }

            return safe.Length > 80 ? safe.Substring(0, 80) : safe;
        }

        private static string ResolveBaseDirectory()
        {
            return Path.IsPathRooted(_baseDirectory)
                ? _baseDirectory
                : Path.Combine(AppContext.BaseDirectory, _baseDirectory);
        }
    }
}
