using System;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
using XGame.Database;
using XGame.Framework.Database;
using XGame.Framework.Json;
using XGame.Framework.Serialization;

namespace FL.Editor.Tests
{
    public static class TestDatabase
    {
        private static string CsvOutput => Application.dataPath.Replace("Assets", "ExtAssets/output/csv");
        [MenuItem("Test/TestDatabase/TablesToCsv")]
        public static void TablesToCsv()
        {
            var outputRoot = CsvOutput;
            if (Directory.Exists(outputRoot))
            {
                Directory.Delete(outputRoot, true);
            }
            Directory.CreateDirectory(outputRoot);
            TableToCsv<ChapterTable, ChapterTableRepo>(ChapterTableRepo.TableName);
            TableToCsv<MapTable, MapTableRepo>(MapTableRepo.TableName);
            TableToCsv<MonsterTable, MonsterTableRepo>(MonsterTableRepo.TableName);
            TableToCsv<SimpleConfigTable, SimpleConfigTableRepo>(SimpleConfigTableRepo.TableName);
        }
        private static void TableToCsv<TTable, TRepository>(string tableName) where TTable : class, ITable where TRepository : TableRepository<TTable, TRepository>
        {
            var tablePath = $"Assets/Res/Dynamic/Tables/{tableName}.bytes";
            var outputPath = $"{CsvOutput}/{tableName.Replace("Table", "")}.csv";
            

            var bytes = AssetDatabase.LoadAssetAtPath<TextAsset>(tablePath).bytes;
            var repo = SerializationUtils.Read<TRepository>(bytes);

            var sb = new StringBuilder();
            var tableType = typeof(TTable);
            var properties = tableType.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
            var fieldNames = string.Empty;
            var fieldTypes = string.Empty;
            var fieldCount = properties.Length;
            for (var i = 0; i < fieldCount; i++)
            {
                var separator = i == fieldCount - 1 ? "" : ",";
                fieldNames += $"\"{properties[i].Name}\"{separator}";
                fieldTypes += $"\"{properties[i].PropertyType.Name}\"{separator}";
            }
            sb.AppendLine(fieldNames);
            sb.AppendLine(fieldTypes);
            //空两行用于和etoy的csv文件保持一致
            sb.AppendLine();
            sb.AppendLine();
            foreach (var table in repo.GetAllTables())
            {
                var fieldValues = string.Empty;
                for (var i = 0; i < fieldCount; i++)
                {
                    var separator = i == fieldCount - 1 ? "" : ",";
                    var fieldType = properties[i].PropertyType;
                    var value = properties[i].GetValue(table);
                    if (fieldType.IsEnum == false && fieldType.Namespace.Contains("XGame.Database"))
                    { // 自定义数据结构
                        if (value is Array array)
                        {
                            var arrayVals = "[";
                            for (var j = 0; j < array.Length; j++)
                            {
                                var item = array.GetValue(j);
                                var itemType = item.GetType();
                                arrayVals += ObjectToString(itemType, item);
                                if (j < array.Length - 1)
                                {
                                    arrayVals += ",";
                                }
                            }
                            arrayVals += "]";
                            value = arrayVals;
                        }
                        else
                        {
                            value = ObjectToString(fieldType, value);
                        }
                    }
                    else
                    {
                        if (fieldType.IsArray)
                        {
                            value = XJson.ToJson(value);
                        }
                    }
                    fieldValues += $"\"{value}\"{separator}";
                }
                sb.AppendLine(fieldValues);
            }
            File.WriteAllText(outputPath, sb.ToString());
            Debug.Log($"TableToCsv Path:{outputPath}");
        }
        private static string ObjectToString(Type type, object obj)
        {
            var fields = type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
            var fieldCount = fields.Length;
            var fieldValues = "{";
            for (var i = 0; i < fieldCount; i++)
            {
                var separator = i == fieldCount - 1 ? "" : ",";
                var fieldType = fields[i].PropertyType;
                var value = fields[i].GetValue(obj);
                if (fieldType.IsArray)
                { //TODO 二次识别自定义数据结构
                    value = XJson.ToJson(value);
                }
                fieldValues += $"{value}{separator}";
            }
            fieldValues += "}";
            return fieldValues;
        }

        //[UnityEditor.MenuItem("Test/TestDatabase/WriteTables")]

        //public static void WriteTables()
        //{
        //    var length = 10;
        //    var tables = new SimpleTable[length];
        //    for (int i = 0; i < length; i++)
        //    {
        //        var table = new SimpleTable()
        //        {
        //            Id = i,
        //            Name = typeof(SimpleTable).Name + i,
        //            SimpleType = (SimpleType)(i % 2)
        //        };
        //        tables[i] = table;
        //    }
        //    var tableRepo = new SimpleTableRepo();

        //    var fileInfo = typeof(SimpleTableRepo).GetField("_tables", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase);
        //    if (fileInfo == null)
        //    {
        //        Debug.LogError($"没找到字段: _tables");
        //        return;
        //    }
        //    fileInfo.SetValue(tableRepo, tables);
        //    var writer = new Writer();
        //    (tableRepo as ISerializable).Serialize(writer);
        //    var bytes = writer.Finish();
        //    var path = $"Assets/Res/Dynamic/Tables/SimpleTable.bytes";
        //    File.WriteAllBytes(path, bytes);

        //    var reader = new Reader(bytes);
        //    var result = Activator.CreateInstance<SimpleTableRepo>() as ISerializable;
        //    result.Deserialize(reader);
        //    AssetDatabase.Refresh();
        //    Debug.Log($"WriteTables End.");
        //}
    }
}

