using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEditor;

[Serializable]
public class ConfigTableInfo
{
    public string tableName;
    public string displayName;
    public string description;
    public List<FieldRelation> relations = new List<FieldRelation>();
    public bool isExistInProject;
    public string fileExtension = ".xlsx";
}

[Serializable]
public class FieldRelation
{
    public string fieldName;
    public string targetTable;
    public string targetField;
    public string relationFormat;
    public string description;
}

public class ReverseRelation
{
    public string sourceTable;
    public string sourceDisplayName;
    public string fieldName;
    public string description;
    public string relationFormat;
}

[Serializable]
public class ConfigLinkDataFile
{
    public List<ConfigLinkTableEntry> tables = new List<ConfigLinkTableEntry>();
}

[Serializable]
public class ConfigLinkTableEntry
{
    public string name;
    public string displayName;
    public string description;
    public string fileExtension;
    public List<ConfigLinkRelation> relations = new List<ConfigLinkRelation>();
}

[Serializable]
public class ConfigLinkRelation
{
    public string field;
    public string target;
    public string targetField;
    public string format;
    public string description;
}

[Serializable]
public class FormatTemplate
{
    public string[] parts;
    public int minParts;
}

[Serializable]
public class SettingsData
{
    public string configFolderPath = "Resources/Resources_moved/config";
    public string excelFolderPath = "";
    public FormatTemplatesWrapper formatTemplates = new FormatTemplatesWrapper();
}

[Serializable]
public class FormatTemplatesWrapper
{
    public FormatTemplate item_id_num = new FormatTemplate { parts = new[] { "类型", "ID", "数量" }, minParts = 3 };
    public FormatTemplate type_id_num = new FormatTemplate { parts = new[] { "类型", "ID", "数量" }, minParts = 3 };
    public FormatTemplate id_pos_lv = new FormatTemplate { parts = new[] { "ID", "位置", "等级" }, minParts = 3 };
    public FormatTemplate id_lv_num = new FormatTemplate { parts = new[] { "ID", "等级", "数量" }, minParts = 3 };
    public FormatTemplate id_lv_num_time = new FormatTemplate { parts = new[] { "ID", "等级", "数量", "时间" }, minParts = 4 };
    public FormatTemplate buffid_lv = new FormatTemplate { parts = new[] { "BuffID", "等级" }, minParts = 2 };
    public FormatTemplate rune_id_num = new FormatTemplate { parts = new[] { "符文ID", "数量" }, minParts = 2 };
    public FormatTemplate equip_id_num = new FormatTemplate { parts = new[] { "装备ID", "数量" }, minParts = 2 };
    public FormatTemplate hero_id = new FormatTemplate { parts = new[] { "英雄ID" }, minParts = 1 };
    public FormatTemplate id_lv_count_delay = new FormatTemplate { parts = new[] { "ID", "等级", "数量", "延迟" }, minParts = 4 };
    public FormatTemplate id_lv_num_hp = new FormatTemplate { parts = new[] { "ID", "等级", "数量", "血量%" }, minParts = 4 };
}

public static class ConfigLinkDatabase
{
    private static List<ConfigTableInfo> _cachedData;
    private static HashSet<string> _existingTableNames;
    private static string _excelFolderPath;
    private static SettingsData _settings;
    private static Dictionary<string, FormatTemplate> _formatTemplateMap;
    private static Dictionary<string, (string displayName, string description)> _tableInfoCache;

    private const string CONFIG_FILE_NAME = "ConfigLinkData.json";
    private const string SETTINGS_FILE_NAME = "settings.json";
    private const string TABLE_INFO_FILE_NAME = "table_info.json";
    private const string EXCEL_PATH_KEY = "ConfigLinkViewer.ExcelFolderPath";

    private static string ViewerDir
    {
        get { return Path.Combine(Application.dataPath, "Editor/ConfigLinkViewer"); }
    }

    private static string ConfigFilePath
    {
        get { return Path.Combine(ViewerDir, CONFIG_FILE_NAME); }
    }

    private static string SettingsFilePath
    {
        get { return Path.Combine(ViewerDir, SETTINGS_FILE_NAME); }
    }

    private static string TableInfoFilePath
    {
        get { return Path.Combine(ViewerDir, TABLE_INFO_FILE_NAME); }
    }

    public static string GetConfigFolderPath()
    {
        LoadSettings();
        return _settings.configFolderPath;
    }

    public static void SetConfigFolderPath(string path)
    {
        LoadSettings();
        _settings.configFolderPath = path;
        SaveSettings();
        ClearCache();
    }

    public static void SetExcelFolderPath(string path)
    {
        _excelFolderPath = path;
        EditorUserSettings.SetConfigValue(EXCEL_PATH_KEY, path);
        ClearCache();
    }

    public static string GetExcelFolderPath()
    {
        if (string.IsNullOrEmpty(_excelFolderPath))
        {
            _excelFolderPath = EditorUserSettings.GetConfigValue(EXCEL_PATH_KEY) ?? "";
        }
        return _excelFolderPath;
    }

    public static string GetExcelFilePath(string tableName)
    {
        string folderPath = GetExcelFolderPath();
        if (string.IsNullOrEmpty(folderPath))
            return null;

        var tableInfo = GetTableInfo(tableName);
        string extension = tableInfo?.fileExtension ?? ".xlsx";
        string excelPath = Path.Combine(folderPath, $"{tableName}{extension}");
        return File.Exists(excelPath) ? excelPath : null;
    }

    public static bool IsExcelFolderSet()
    {
        return !string.IsNullOrEmpty(GetExcelFolderPath());
    }

    public static bool IsExcelFileExists(string tableName)
    {
        return GetExcelFilePath(tableName) != null;
    }

    public static List<ConfigTableInfo> GetAllTableInfo()
    {
        if (_cachedData != null)
            return _cachedData;

        _cachedData = LoadConfigFromFile(ConfigFilePath);
        MarkExistingTables();
        return _cachedData;
    }

    public static bool IsConfigLoaded()
    {
        return _cachedData != null && _cachedData.Count > 0;
    }

    public static bool HasConfigFile()
    {
        return File.Exists(ConfigFilePath);
    }

    private static List<ConfigTableInfo> LoadConfigFromFile(string path)
    {
        if (!File.Exists(path))
        {
            Debug.LogWarning("[ConfigLinkViewer] 配置文件不存在，请点击[生成配置]按钮生成: " + path);
            return new List<ConfigTableInfo>();
        }

        try
        {
            string json = File.ReadAllText(path, Encoding.UTF8);
            var data = JsonUtility.FromJson<ConfigLinkDataFile>(json);
            if (data == null || data.tables == null) return new List<ConfigTableInfo>();

            var result = new List<ConfigTableInfo>();
            foreach (var entry in data.tables)
            {
                var info = new ConfigTableInfo
                {
                    tableName = entry.name,
                    displayName = string.IsNullOrEmpty(entry.displayName) ? entry.name : entry.displayName,
                    description = entry.description ?? "",
                    fileExtension = string.IsNullOrEmpty(entry.fileExtension) ? ".xlsx" : entry.fileExtension,
                    relations = new List<FieldRelation>()
                };

                if (entry.relations != null)
                {
                    foreach (var rel in entry.relations)
                    {
                        info.relations.Add(new FieldRelation
                        {
                            fieldName = rel.field,
                            targetTable = rel.target,
                            targetField = rel.targetField ?? "id",
                            relationFormat = rel.format ?? "",
                            description = rel.description ?? ""
                        });
                    }
                }

                result.Add(info);
            }

            return result;
        }
        catch (Exception e)
        {
            Debug.LogError($"[ConfigLinkViewer] 加载配置文件失败: {e.Message}");
            return new List<ConfigTableInfo>();
        }
    }

    public static void GenerateConfigFromExcelFolder()
    {
        string excelFolder = GetExcelFolderPath();
        if (string.IsNullOrEmpty(excelFolder) || !Directory.Exists(excelFolder))
        {
            EditorUtility.DisplayDialog("提示", "请先设置Excel文件夹路径", "确定");
            return;
        }

        var files = Directory.GetFiles(excelFolder, "*.xlsx", SearchOption.AllDirectories)
            .Where(f => !Path.GetFileName(f).StartsWith("~$"))
            .ToArray();

        if (files.Length == 0)
        {
            EditorUtility.DisplayDialog("提示", "Excel文件夹中未找到.xlsx文件", "确定");
            return;
        }

        var data = new ConfigLinkDataFile();
        var tableInfoDict = LoadTableInfoDict();

        foreach (var file in files)
        {
            string name = Path.GetFileNameWithoutExtension(file);
            string displayName = name;
            string description = "";

            if (tableInfoDict.TryGetValue(name.ToLower(), out var ti))
            {
                displayName = ti.Item1;
                description = ti.Item2;
            }

            data.tables.Add(new ConfigLinkTableEntry
            {
                name = name,
                displayName = displayName,
                description = description,
                fileExtension = ".xlsx",
                relations = new List<ConfigLinkRelation>()
            });
        }

        var txtFiles = Directory.GetFiles(excelFolder, "*.txt", SearchOption.AllDirectories);
        foreach (var file in txtFiles)
        {
            string name = Path.GetFileNameWithoutExtension(file);
            string displayName = name;
            string description = "";

            if (tableInfoDict.TryGetValue(name.ToLower(), out var ti))
            {
                displayName = ti.Item1;
                description = ti.Item2;
            }

            data.tables.Add(new ConfigLinkTableEntry
            {
                name = name,
                displayName = displayName,
                description = description,
                fileExtension = ".txt",
                relations = new List<ConfigLinkRelation>()
            });
        }

        string json = JsonUtility.ToJson(data, true);
        File.WriteAllText(ConfigFilePath, json, Encoding.UTF8);

        ClearCache();
        AssetDatabase.Refresh();
        EditorUtility.DisplayDialog("生成完成",
            $"已扫描 {files.Length} 个文件，生成配置文件\n\n" +
            $"配置文件: {ConfigFilePath}\n\n" +
            $"提示: 可将该文件交给 AI 补全中文名称和表间关联关系", "确定");
    }

    private static void MarkExistingTables()
    {
        _existingTableNames = new HashSet<string>();

        string configPath = Path.Combine(Application.dataPath, GetConfigFolderPath());
        if (Directory.Exists(configPath))
        {
            string[] jsonFiles = Directory.GetFiles(configPath, "*.json");
            foreach (string file in jsonFiles)
            {
                string tableName = Path.GetFileNameWithoutExtension(file);
                _existingTableNames.Add(tableName.ToLower());
            }
        }

        if (_cachedData == null) return;

        foreach (var table in _cachedData)
        {
            bool existInConfig = _existingTableNames.Contains(table.tableName.ToLower());

            if (!existInConfig && table.fileExtension == ".txt")
            {
                string excelFolderPath = GetExcelFolderPath();
                if (!string.IsNullOrEmpty(excelFolderPath))
                {
                    string txtPath = Path.Combine(excelFolderPath, $"{table.tableName}{table.fileExtension}");
                    existInConfig = File.Exists(txtPath);
                }
            }

            table.isExistInProject = existInConfig;
        }
    }

    public static bool IsTableExistInConfigFolder(string tableName)
    {
        string configPath = Path.Combine(Application.dataPath, GetConfigFolderPath());
        if (!Directory.Exists(configPath))
            return false;

        var tableInfo = GetTableInfo(tableName);
        string extension = tableInfo?.fileExtension ?? ".xlsx";

        string jsonPath = Path.Combine(configPath, $"{tableName}.json");

        if (extension == ".txt")
        {
            string excelFolderPath = GetExcelFolderPath();
            if (!string.IsNullOrEmpty(excelFolderPath))
            {
                string txtPath = Path.Combine(excelFolderPath, $"{tableName}{extension}");
                if (File.Exists(txtPath))
                    return true;
            }
        }

        return File.Exists(jsonPath);
    }

    public static ConfigTableInfo GetTableInfo(string tableName)
    {
        return GetAllTableInfo().Find(x => x.tableName.Equals(tableName, StringComparison.OrdinalIgnoreCase));
    }

    public static List<string> GetAllTableNames()
    {
        return GetAllTableInfo().ConvertAll(x => x.tableName);
    }

    public static List<ReverseRelation> GetReverseRelations(string targetTableName)
    {
        List<ReverseRelation> result = new List<ReverseRelation>();

        foreach (var table in GetAllTableInfo())
        {
            foreach (var relation in table.relations)
            {
                if (relation.targetTable.Equals(targetTableName, StringComparison.OrdinalIgnoreCase))
                {
                    result.Add(new ReverseRelation
                    {
                        sourceTable = table.tableName,
                        sourceDisplayName = table.displayName,
                        fieldName = relation.fieldName,
                        description = relation.description,
                        relationFormat = relation.relationFormat
                    });
                }
            }
        }

        return result;
    }

    public static string FormatRelationValue(string format, string value)
    {
        if (string.IsNullOrEmpty(format) || string.IsNullOrEmpty(value))
            return value;

        string key = format.ToLower();

        if (key == "表名")
            return $"表名: {value}";

        LoadFormatTemplates();

        if (_formatTemplateMap.TryGetValue(key, out var template))
        {
            string[] parts = value.Split('_');
            if (parts.Length >= template.minParts)
            {
                var sb = new StringBuilder();
                for (int i = 0; i < template.parts.Length && i < parts.Length; i++)
                {
                    if (i > 0) sb.Append(", ");
                    sb.Append($"{template.parts[i]}:{parts[i]}");
                }
                return sb.ToString();
            }
        }

        return value;
    }

    public static List<string> GetRelatedTableNames(string tableName)
    {
        var tableInfo = GetTableInfo(tableName);
        if (tableInfo == null)
            return new List<string>();

        return tableInfo.relations.Select(r => r.targetTable).Distinct().ToList();
    }

    public static List<string> GetAllDisplayNames()
    {
        return GetAllTableInfo().ConvertAll(x => $"{x.displayName} ({x.tableName})");
    }

    public static List<ConfigTableInfo> GetExistingTables()
    {
        return GetAllTableInfo().Where(x => x.isExistInProject).ToList();
    }

    public static bool IsTableExist(string tableName)
    {
        if (_existingTableNames == null)
        {
            GetAllTableInfo();
        }
        return _existingTableNames.Contains(tableName.ToLower());
    }

    public static void ClearCache()
    {
        _cachedData = null;
        _existingTableNames = null;
        _settings = null;
        _formatTemplateMap = null;
        _tableInfoCache = null;
    }

    /// <summary>
    /// 获取所有缺少中文配置的表（displayName == name 或 description 为空）
    /// </summary>
    public static List<ConfigTableInfo> GetTablesMissingChineseConfig()
    {
        return GetAllTableInfo().Where(table => 
            string.IsNullOrEmpty(table.displayName) || 
            table.displayName.Equals(table.tableName, StringComparison.OrdinalIgnoreCase) ||
            string.IsNullOrEmpty(table.description)
        ).ToList();
    }

    /// <summary>
    /// 检查是否存在缺少中文配置的表
    /// </summary>
    public static bool HasTablesMissingChineseConfig()
    {
        return GetTablesMissingChineseConfig().Count > 0;
    }

    /// <summary>
    /// 输出缺少中文配置的表信息到控制台
    /// </summary>
    public static void LogMissingChineseConfig()
    {
        var missingTables = GetTablesMissingChineseConfig();
        if (missingTables.Count == 0)
        {
            Debug.Log("[ConfigLinkViewer] 所有表均已配置中文名称和描述");
            return;
        }

        StringBuilder sb = new StringBuilder();
        sb.AppendLine($"[ConfigLinkViewer] 发现 {missingTables.Count} 个表缺少中文配置：");
        foreach (var table in missingTables)
        {
            sb.AppendLine($"  - {table.tableName}: displayName='{table.displayName}', description='{table.description}'");
        }
        sb.AppendLine("建议使用智能体辅助补充中文配置。");
        Debug.Log(sb.ToString());
    }

    private static void LoadSettings()
    {
        if (_settings != null) return;

        if (File.Exists(SettingsFilePath))
        {
            try
            {
                string json = File.ReadAllText(SettingsFilePath, Encoding.UTF8);
                _settings = JsonUtility.FromJson<SettingsData>(json);
            }
            catch (Exception e)
            {
                Debug.LogWarning($"[ConfigLinkViewer] 加载 settings.json 失败: {e.Message}");
                _settings = new SettingsData();
            }
        }
        else
        {
            _settings = new SettingsData();
        }
    }

    public static void SaveSettings()
    {
        try
        {
            string json = JsonUtility.ToJson(_settings, true);
            File.WriteAllText(SettingsFilePath, json, Encoding.UTF8);
        }
        catch (Exception e)
        {
            Debug.LogError($"[ConfigLinkViewer] 保存 settings.json 失败: {e.Message}");
        }
    }

    private static void LoadFormatTemplates()
    {
        if (_formatTemplateMap != null) return;

        _formatTemplateMap = new Dictionary<string, FormatTemplate>();
        LoadSettings();

        if (_settings.formatTemplates != null)
        {
            var wrapperType = typeof(FormatTemplatesWrapper);
            var fields = wrapperType.GetFields();
            foreach (var field in fields)
            {
                if (field.FieldType == typeof(FormatTemplate))
                {
                    var template = field.GetValue(_settings.formatTemplates) as FormatTemplate;
                    if (template != null)
                    {
                        _formatTemplateMap[field.Name] = template;
                    }
                }
            }
        }
    }

    private static Dictionary<string, (string, string)> LoadTableInfoDict()
    {
        if (_tableInfoCache != null)
            return _tableInfoCache;

        _tableInfoCache = new Dictionary<string, (string, string)>();

        if (!File.Exists(TableInfoFilePath))
            return _tableInfoCache;

        try
        {
            string json = File.ReadAllText(TableInfoFilePath, Encoding.UTF8);
            var raw = JsonUtility.FromJson<TableInfoFile>(json);
            if (raw?.entries != null)
            {
                foreach (var entry in raw.entries)
                {
                    if (!string.IsNullOrEmpty(entry.name))
                    {
                        _tableInfoCache[entry.name.ToLower()] = (
                            entry.displayName ?? entry.name,
                            entry.description ?? ""
                        );
                    }
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogWarning($"[ConfigLinkViewer] 加载 table_info.json 失败: {e.Message}");
        }

        return _tableInfoCache;
    }

    [Serializable]
    private class TableInfoFile
    {
        public List<TableInfoEntry> entries = new List<TableInfoEntry>();
    }

    [Serializable]
    private class TableInfoEntry
    {
        public string name;
        public string displayName;
        public string description;
    }
}
