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

namespace AxCopilot.Services;

/// <summary>
/// 에이전트 도구 호출 이력을 로컬 JSON 파일로 영속화하는 보안 감사 로그 서비스.
/// 파일 위치: %APPDATA%\AxCopilot\audit\{yyyy-MM-dd}.json
/// </summary>
public static class AuditLogService
{
    private static readonly string AuditDir;
    private static readonly object _lock = new();
    private static readonly JsonSerializerOptions _jsonOpts = new()
    {
        WriteIndented = false,
        Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    };

    static AuditLogService()
    {
        AuditDir = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
            "AxCopilot", "audit");
        try { Directory.CreateDirectory(AuditDir); } catch (Exception) { }
    }

    /// <summary>감사 로그 항목을 기록합니다.</summary>
    public static void Log(AuditEntry entry)
    {
        try
        {
            var fileName = $"{DateTime.Now:yyyy-MM-dd}.json";
            var filePath = Path.Combine(AuditDir, fileName);
            var json = JsonSerializer.Serialize(entry, _jsonOpts);

            lock (_lock)
            {
                File.AppendAllText(filePath, json + "\n", Encoding.UTF8);
            }
        }
        catch (Exception) { /* 감사 로그 실패는 무시 — 앱 동작에 영향 없음 */ }
    }

    /// <summary>에이전트 도구 호출을 감사 로그에 기록합니다.</summary>
    public static void LogToolCall(string conversationId, string tab, string toolName,
        string parameters, string result, string? filePath, bool success)
    {
        Log(new AuditEntry
        {
            ConversationId = conversationId,
            Tab = tab,
            Action = "ToolCall",
            ToolName = toolName,
            Parameters = Truncate(parameters, 500),
            Result = Truncate(result, 500),
            FilePath = filePath,
            Success = success,
        });
    }

    /// <summary>파일 접근을 감사 로그에 기록합니다.</summary>
    public static void LogFileAccess(string conversationId, string tab, string action, string filePath, bool success)
    {
        Log(new AuditEntry
        {
            ConversationId = conversationId,
            Tab = tab,
            Action = action, // Read, Write, Delete, Execute
            FilePath = filePath,
            Success = success,
        });
    }

    /// <summary>오늘 감사 로그를 읽습니다.</summary>
    public static List<AuditEntry> LoadToday()
    {
        var fileName = $"{DateTime.Now:yyyy-MM-dd}.json";
        return LoadFile(Path.Combine(AuditDir, fileName));
    }

    /// <summary>특정 날짜의 감사 로그를 읽습니다.</summary>
    public static List<AuditEntry> LoadDate(DateTime date)
    {
        var fileName = $"{date:yyyy-MM-dd}.json";
        return LoadFile(Path.Combine(AuditDir, fileName));
    }

    private static List<AuditEntry> LoadFile(string filePath)
    {
        var entries = new List<AuditEntry>();
        if (!File.Exists(filePath)) return entries;
        try
        {
            foreach (var line in File.ReadAllLines(filePath, Encoding.UTF8))
            {
                if (string.IsNullOrWhiteSpace(line)) continue;
                var entry = JsonSerializer.Deserialize<AuditEntry>(line, _jsonOpts);
                if (entry != null) entries.Add(entry);
            }
        }
        catch (Exception) { }
        return entries;
    }

    /// <summary>30일 이전 감사 로그를 삭제합니다.</summary>
    public static void PurgeOldLogs(int retentionDays = 30)
    {
        try
        {
            var cutoff = DateTime.Now.AddDays(-retentionDays);
            foreach (var f in Directory.GetFiles(AuditDir, "*.json"))
            {
                if (File.GetCreationTime(f) < cutoff)
                    File.Delete(f);
            }
        }
        catch (Exception) { }
    }

    /// <summary>감사 로그 폴더 경로를 반환합니다.</summary>
    public static string GetAuditFolder() => AuditDir;

    private static string Truncate(string? s, int maxLen) =>
        string.IsNullOrEmpty(s) ? "" : s.Length <= maxLen ? s : s[..maxLen] + "…";
}

/// <summary>감사 로그 항목.</summary>
public class AuditEntry
{
    public DateTime Timestamp { get; init; } = DateTime.Now;
    public string ConversationId { get; init; } = "";
    public string Tab { get; init; } = "";       // Chat, Cowork, Code
    public string Action { get; init; } = "";     // ToolCall, Read, Write, Delete, Execute
    public string ToolName { get; init; } = "";
    public string Parameters { get; init; } = "";
    public string Result { get; init; } = "";
    public string? FilePath { get; init; }
    public bool Success { get; init; } = true;
}
