using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

namespace Eden.AutoMorpher
{
    public enum Language
    {
        Korean = 0,
        Japanese = 1,
        English = 2,
    }

    [Serializable]
    public class LocalizationEntry
    {
        public string key;
        public string value;
    }

    [Serializable]
    public class LocalizationFile
    {
        public LocalizationEntry[] entries;
    }
    
#if UNITY_EDITOR
    [InitializeOnLoad]
#endif
    public static class LanguageManager
    {
        private const string PREF_KEY_LANG = "EdenAutoMorpher_Language";

        private const string PATH_KO = "Language/Language_ko";
        private const string PATH_JA = "Language/Language_ja";
        private const string PATH_EN = "Language/Language_en";

        private static Language _currentLanguage = Language.Korean;

        private static Dictionary<string, string> _koTable;
        private static Dictionary<string, string> _jaTable;
        private static Dictionary<string, string> _enTable;

        public static Language CurrentLanguage
        {
            get => _currentLanguage;
            set
            {
                if (_currentLanguage == value) return;
                _currentLanguage = value;
#if UNITY_EDITOR
                EditorPrefs.SetInt(PREF_KEY_LANG, (int)_currentLanguage);
#else
                PlayerPrefs.SetInt(PREF_KEY_LANG, (int)_currentLanguage);
                PlayerPrefs.Save();
#endif
            }
        }

        static LanguageManager()
        {
            // Editor 시작 시 언어 로드
#if UNITY_EDITOR
            int saved = EditorPrefs.GetInt(PREF_KEY_LANG, (int)Language.Korean);
#else
            int saved = PlayerPrefs.GetInt(PREF_KEY_LANG, (int)Language.Korean);
#endif
            _currentLanguage = (Language)Mathf.Clamp(saved, 0, 2);
        }

        /// <summary>
        /// 현재 언어에서 문자열 가져오기.
        /// key 없으면 fallback → 다른 언어 → 최종적으로 key 자체 반환.
        /// </summary>
        public static string Get(string key)
        {
            if (string.IsNullOrEmpty(key))
                return string.Empty;

            // 현재 언어 테이블에서 먼저 검색
            if (TryGetFromCurrentLanguage(key, out string value))
                return value;

            return FormatKeyNotFound(key);
        }

        /// <summary>
        /// 언어별로 다른 키를 쓰고 싶을 때 (번호 기반 등)도 가능하도록
        /// 번호를 바로 key 문자열로 변환해서 사용하는 버전.
        /// </summary>
        public static string GetById(int id)
        {
            // 예: "ID.1001" 이런 식으로 통일하면 관리가 편함
            string key = $"ID.{id}";
            return Get(key);
        }

        public static void SetLanguage(Language lang)
        {
            CurrentLanguage = lang;
        }

        // ================== 내부 구현 ==================

        private static bool TryGetFromCurrentLanguage(string key, out string value)
        {
            var table = GetTable(_currentLanguage);
            if (table != null && table.TryGetValue(key, out value))
                return true;

            value = null;
            return false;
        }

        private static bool TryGetFromOtherLanguages(string key, out string value)
        {
            // 현재 언어 제외한 나머지 순회
            foreach (Language lang in System.Enum.GetValues(typeof(Language)))
            {
                if (lang == _currentLanguage)
                    continue;

                var table = GetTable(lang);
                if (table != null && table.TryGetValue(key, out value))
                    return true;
            }

            value = null;
            return false;
        }

        private static Dictionary<string, string> GetTable(Language lang)
        {
            switch (lang)
            {
                case Language.Korean:
                    if (_koTable == null)
                        _koTable = LoadTable(PATH_KO);
                    return _koTable;

                case Language.Japanese:
                    if (_jaTable == null)
                        _jaTable = LoadTable(PATH_JA);
                    return _jaTable;

                case Language.English:
                    if (_enTable == null)
                        _enTable = LoadTable(PATH_EN);
                    return _enTable;

                default:
                    return null;
            }
        }

        // fileName: "lang_ko", "lang_ja", "lang_en" 처럼 사용
        private static Dictionary<string, string> LoadTable(string fileName)
        {
            var dict = new Dictionary<string, string>();

#if UNITY_EDITOR
            // 스크립트 기준 Language 폴더 아래의 json 경로
            string assetPath = GetLanguageJsonAssetPath(fileName);
            // Assets/... 형식 경로를 실제 디스크 경로로 변환
            string fullPath = Path.GetFullPath(assetPath);

            if (!File.Exists(fullPath))
            {
                Debug.LogWarning($"[AutoMorpherLanguage] Localization file not found: {fullPath}");
                return dict;
            }

            string jsonText;
            try
            {
                // ✅ 강제로 UTF-8 로 읽기 (BOM 유무 상관 없음)
                jsonText = File.ReadAllText(fullPath, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
            }
            catch (System.Exception ex)
            {
                Debug.LogError($"[AutoMorpherLanguage] Failed to read localization file: {fullPath}\n{ex}");
                return dict;
            }

            try
            {
                var file = JsonUtility.FromJson<LocalizationFile>(jsonText);
                if (file?.entries != null)
                {
                    foreach (var entry in file.entries)
                    {
                        if (string.IsNullOrEmpty(entry.key))
                            continue;

                        dict[entry.key] = entry.value ?? string.Empty;
                    }
                }
            }
            catch (System.Exception ex)
            {
                Debug.LogError($"[AutoMorpherLanguage] Failed to parse localization file: {fullPath}\n{ex}");
            }
#else
            // 런타임 빌드에서 쓸 계획이 없으면 비워둬도 됨
#endif
            return dict;
        }
        private static string FormatKeyNotFound(string key)
        {
            // 먼저 현재 언어의 "Error.KeyNotFound" 가져오기
            if (TryGetFromCurrentLanguage("Error.KeyNotFound", out string template))
                return template.Replace("{0}", key);

            // JSON 자체가 없어서 템플릿도 없는 경우 (최후 fallback)
            switch (CurrentLanguage)
            {
                case Language.Korean:
                    return $"[KO] 해당 키를 찾을 수 없습니다: {key}";
                case Language.Japanese:
                    return $"[JP] キーが見つかりません: {key}";
                default:
                    return $"[EN] Could not find key: {key}";
            }
        }
        
        
        public static string GetLanguageFolderPath()
        {
            string scriptDir = "Assets\\@Eden_Tools\\Eden_AutoMorpher\\LanguageManager\\Language";
#if UNITY_EDITOR
            // AutoMorpherLanguage 스크립트의 GUID 찾기
            string[] guids = AssetDatabase.FindAssets("LanguageManager t:MonoScript");
            if (guids == null || guids.Length == 0)
            {
                Debug.LogError("[LanguageManager] Could not find LanguageManager.cs script.");
                return "Assets"; // 최소 fallback
            }

            string scriptPath = AssetDatabase.GUIDToAssetPath(guids[0]); // 예: Assets/@Eden_Tools/.../AutoMorpherLanguage.cs
            scriptDir = Path.GetDirectoryName(scriptPath);        // 그 폴더


            // 폴더가 없으면 에디터에서 자동 생성
            if (!Directory.Exists(scriptDir))
            {
                Directory.CreateDirectory(scriptDir);
                AssetDatabase.Refresh();
            }
#endif
            // Unity Asset 경로 포맷으로 정리
            scriptDir = scriptDir.Replace("\\", "/");
            return scriptDir;
        }

        public static string GetLanguageJsonAssetPath(string fileNameWithoutExt)
        {
            string folder = GetLanguageFolderPath();
            string path = Path.Combine(folder, fileNameWithoutExt + ".json");
            return path.Replace("\\", "/");
        }
        
        public static string GetFormat(string key, params object[] args)
        {
            string raw = Get(key);
            if (string.IsNullOrEmpty(raw))
                return string.Empty;

            try
            {
                return string.Format(raw, args);
            }
            catch (Exception ex)
            {
                Debug.LogError($"[LanguageManager] Format failed for key: {key}\n{ex}");
                return raw; // 최소한 원문이라도 보여주기
            }
        }

    }
}
