using System.IO;

namespace AxCopilot.Services;

/// <summary>
/// 앱의 저장 공간 사용량을 분석하고 정리 기능을 제공합니다.
/// </summary>
public static class StorageAnalyzer
{
    private static readonly string AppDataDir = Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot");

    /// <summary>저장 공간 분석 결과를 반환합니다.</summary>
    public static StorageReport Analyze()
    {
        var report = new StorageReport();

        // 앱 데이터 폴더별 크기 계산
        report.Conversations = GetFolderSize(Path.Combine(AppDataDir, "conversations"));
        report.AuditLogs = GetFolderSize(Path.Combine(AppDataDir, "audit"));
        report.Logs = GetFolderSize(Path.Combine(AppDataDir, "logs"));
        report.CodeIndex = GetFolderSize(Path.Combine(AppDataDir, "code_index"));
        report.EmbeddingDb = GetFolderSize(Path.Combine(AppDataDir, "embeddings"));
        report.ClipboardHistory = GetFileSize(Path.Combine(AppDataDir, "clipboard_history.dat"));
        report.Plugins = GetFolderSize(Path.Combine(AppDataDir, "plugins"));
        report.Skills = GetFolderSize(Path.Combine(AppDataDir, "skills"));
        report.Settings = GetFileSize(Path.Combine(AppDataDir, "settings.json"));

        // 앱 실행 파일 위치의 드라이브 여유 공간
        var exeDir = Path.GetDirectoryName(Environment.ProcessPath) ?? AppDataDir;
        try
        {
            var drive = new DriveInfo(Path.GetPathRoot(exeDir) ?? "C:");
            report.DriveLabel = drive.Name;
            report.DriveFreeSpace = drive.AvailableFreeSpace;
            report.DriveTotalSpace = drive.TotalSize;
        }
        catch (Exception) { }

        return report;
    }

    /// <summary>지정된 기간보다 오래된 데이터를 삭제합니다.</summary>
    /// <param name="retainDays">보관 일수 (7/14/30). 0이면 전체 삭제.</param>
    /// <returns>삭제된 바이트 수</returns>
    public static long Cleanup(int retainDays, bool cleanConversations, bool cleanAuditLogs,
        bool cleanLogs, bool cleanCodeIndex, bool cleanClipboard)
    {
        long freed = 0;
        var cutoff = DateTime.Now.AddDays(-retainDays);

        if (cleanConversations)
            freed += CleanFolder(Path.Combine(AppDataDir, "conversations"), cutoff, retainDays == 0);

        if (cleanAuditLogs)
            freed += CleanFolder(Path.Combine(AppDataDir, "audit"), cutoff, retainDays == 0);

        if (cleanLogs)
            freed += CleanFolder(Path.Combine(AppDataDir, "logs"), cutoff, retainDays == 0);

        if (cleanCodeIndex)
            freed += CleanFolder(Path.Combine(AppDataDir, "code_index"), cutoff, true); // 인덱스는 전체 삭제

        if (cleanClipboard)
        {
            var clipFile = Path.Combine(AppDataDir, "clipboard_history.dat");
            if (File.Exists(clipFile))
            {
                freed += new FileInfo(clipFile).Length;
                File.Delete(clipFile);
            }
        }

        return freed;
    }

    private static long GetFolderSize(string path)
    {
        if (!Directory.Exists(path)) return 0;
        try
        {
            return Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories)
                .Sum(f => { try { return new FileInfo(f).Length; } catch (Exception) { return 0; } });
        }
        catch (Exception) { return 0; }
    }

    private static long GetFileSize(string path)
    {
        try { return File.Exists(path) ? new FileInfo(path).Length : 0; }
        catch (Exception) { return 0; }
    }

    private static long CleanFolder(string path, DateTime cutoff, bool deleteAll)
    {
        if (!Directory.Exists(path)) return 0;
        long freed = 0;

        foreach (var file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories))
        {
            try
            {
                var fi = new FileInfo(file);
                if (deleteAll || fi.LastWriteTime < cutoff)
                {
                    freed += fi.Length;
                    fi.Delete();
                }
            }
            catch (Exception) { }
        }

        // 빈 디렉토리 정리
        if (deleteAll)
        {
            try { Directory.Delete(path, true); Directory.CreateDirectory(path); } catch (Exception) { }
        }

        return freed;
    }

    /// <summary>바이트를 읽기 좋은 형태로 변환합니다.</summary>
    public static string FormatSize(long bytes)
    {
        if (bytes < 1024) return $"{bytes} B";
        if (bytes < 1024 * 1024) return $"{bytes / 1024.0:F1} KB";
        if (bytes < 1024L * 1024 * 1024) return $"{bytes / (1024.0 * 1024):F1} MB";
        return $"{bytes / (1024.0 * 1024 * 1024):F2} GB";
    }
}

/// <summary>저장 공간 분석 결과.</summary>
public class StorageReport
{
    public long Conversations { get; set; }
    public long AuditLogs { get; set; }
    public long Logs { get; set; }
    public long CodeIndex { get; set; }
    public long EmbeddingDb { get; set; }
    public long ClipboardHistory { get; set; }
    public long Plugins { get; set; }
    public long Skills { get; set; }
    public long Settings { get; set; }

    public string DriveLabel { get; set; } = "";
    public long DriveFreeSpace { get; set; }
    public long DriveTotalSpace { get; set; }

    /// <summary>앱 전체 사용량.</summary>
    public long TotalAppUsage => Conversations + AuditLogs + Logs + CodeIndex + EmbeddingDb + ClipboardHistory + Plugins + Skills + Settings;
}
