using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using AxCopilot.Models;

namespace AxCopilot.Services;

public class SettingsService
{
	private static readonly string AppDataDir = InitAppDataDir();

	public static readonly string SettingsPath = Path.Combine(AppDataDir, "settings.dat");

	private static readonly string LegacyJsonPath = Path.Combine(AppDataDir, "settings.json");

	private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions
	{
		WriteIndented = true,
		PropertyNameCaseInsensitive = true
	};

	private AppSettings _settings = new AppSettings();

	private const string CurrentSettingsVersion = "1.2";

	public AppSettings Settings => _settings;

	public string? MigrationSummary { get; private set; }

	public event EventHandler? SettingsChanged;

	private static string InitAppDataDir()
	{
		string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
		string text = Path.Combine(folderPath, "AxCopilot");
		string text2 = Path.Combine(folderPath, "AxCommander");
		if (!Directory.Exists(text) && Directory.Exists(text2))
		{
			try
			{
				Directory.Move(text2, text);
			}
			catch
			{
			}
		}
		return text;
	}

	public void Load()
	{
		EnsureDirectories();
		if (File.Exists(SettingsPath))
		{
			try
			{
				string @base = File.ReadAllText(SettingsPath);
				string text = CryptoService.PortableDecrypt(@base);
				if (string.IsNullOrEmpty(text))
				{
					throw new InvalidOperationException("복호화 결과가 비어 있습니다.");
				}
				_settings = JsonSerializer.Deserialize<AppSettings>(text, JsonOptions) ?? new AppSettings();
				MigrateIfNeeded();
				return;
			}
			catch (Exception ex)
			{
				string destFileName = SettingsPath + ".bak";
				try
				{
					File.Copy(SettingsPath, destFileName, overwrite: true);
				}
				catch (Exception ex2)
				{
					LogService.Warn("settings.dat 백업 실패: " + ex2.Message);
				}
				LogService.Error("settings.dat 복호화/파싱 실패, 기본값으로 복구: " + ex.Message);
			}
		}
		if (File.Exists(LegacyJsonPath))
		{
			try
			{
				string json = File.ReadAllText(LegacyJsonPath);
				_settings = JsonSerializer.Deserialize<AppSettings>(json, JsonOptions) ?? new AppSettings();
				MigrateIfNeeded();
				Save();
				try
				{
					File.Delete(LegacyJsonPath);
				}
				catch (Exception ex3)
				{
					LogService.Warn("레거시 settings.json 삭제 실패: " + ex3.Message);
				}
				LogService.Info("설정 마이그레이션: settings.json → settings.dat (암호화 적용)");
				return;
			}
			catch (Exception ex4)
			{
				LogService.Error("레거시 settings.json 파싱 실패: " + ex4.Message);
			}
		}
		_settings = CreateDefaults();
		_settings.Version = "1.2";
		Save();
	}

	private void MigrateIfNeeded()
	{
		string current = _settings.Version ?? "1.0";
		bool flag = false;
		if (IsVersionLessThan(current, "1.1"))
		{
			foreach (AliasEntry item in _settings.Aliases.Where((AliasEntry a) => a.Type == "folder"))
			{
				if (item.Key.StartsWith("~"))
				{
					item.Key = "cd " + item.Key.TrimStart('~');
				}
			}
			LogService.Info("설정 마이그레이션: 1.0 → 1.1 (폴더 별칭 prefix ~ → cd)");
			current = "1.1";
			flag = true;
		}
		if (IsVersionLessThan(current, "1.2"))
		{
			_settings.Launcher.EnableFileDialogIntegration = false;
			LogService.Info("설정 마이그레이션: 1.1 → 1.2 (파일 대화상자 연동 비활성화)");
			current = "1.2";
			flag = true;
		}
		if (flag)
		{
			_settings.Version = "1.2";
			Save();
			MigrationSummary = "설정이 v1.2으로 업데이트되었습니다.\n\n• 파일 대화상자 연동 기능이 비활성화되었습니다.\n  웹 브라우저 파일 업로드 시 런처가 열리는 문제를 방지합니다.\n  필요 시 설정 → 기능 → AI 기능에서 다시 활성화할 수 있습니다.";
			LogService.Info("설정 파일 마이그레이션 완료 → v1.2");
		}
	}

	private static bool IsVersionLessThan(string current, string target)
	{
		if (Version.TryParse(current, out Version result) && Version.TryParse(target, out Version result2))
		{
			return result < result2;
		}
		return string.Compare(current, target, StringComparison.Ordinal) < 0;
	}

	public void Save()
	{
		EnsureDirectories();
		string plainText = JsonSerializer.Serialize(_settings, JsonOptions);
		string contents = CryptoService.PortableEncrypt(plainText);
		File.WriteAllText(SettingsPath, contents);
		this.SettingsChanged?.Invoke(this, EventArgs.Empty);
	}

	private static void EnsureDirectories()
	{
		Directory.CreateDirectory(AppDataDir);
		Directory.CreateDirectory(Path.Combine(AppDataDir, "logs"));
		Directory.CreateDirectory(Path.Combine(AppDataDir, "crashes"));
		Directory.CreateDirectory(Path.Combine(AppDataDir, "skills"));
	}

	private static AppSettings CreateDefaults()
	{
		List<string> list = new List<string> { "%USERPROFILE%\\Desktop", "%APPDATA%\\Microsoft\\Windows\\Start Menu" };
		if (Directory.Exists("D:\\Non_Documents"))
		{
			list.Add("D:\\Non_Documents");
		}
		return new AppSettings
		{
			IndexPaths = list,
			Aliases = new List<AliasEntry>
			{
				new AliasEntry
				{
					Key = "@blog",
					Type = "url",
					Target = "https://example.com",
					Description = "내 블로그"
				},
				new AliasEntry
				{
					Key = "~home",
					Type = "folder",
					Target = "%USERPROFILE%",
					Description = "홈 폴더"
				}
			},
			Launcher = new LauncherSettings
			{
				CustomTheme = new CustomThemeColors()
			}
		};
	}
}
