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

namespace RKOKO.Config.Free.Editor
{
    public class RKOKOExportReportWindow : EditorWindow
    {
        public class ReportData
        {
            public bool Success;
            public string ExcelDir;
            public string OutputDir;
            public string JsonExportDir;
            public string CsharpExportDir;
            public string ErrorMessage;
            public string ErrorDetail;
            public int SheetCount;
            public int GeneratedFileCount;
            public readonly List<string> InfoLogs = new List<string>();
            public readonly List<string> ErrorLogs = new List<string>();
        }

        private ReportData _data;
        private Vector2 _scroll;
        private Vector2 _errorScroll;
        private Vector2 _logScroll;
        private bool _showLogs;
        private bool _showSummary;

        public static void Show(ReportData data)
        {
            var window = GetWindow<RKOKOExportReportWindow>(true,
                EditorLocalize.Get(data != null && data.Success ? 1036 : 1037), true);
            window.minSize = new Vector2(640, 520);
            window._data = data ?? new ReportData();
            window._showLogs = !(data != null && data.Success);
            window._showSummary = false;
            window._scroll = Vector2.zero;
            window._errorScroll = Vector2.zero;
            window._logScroll = Vector2.zero;
            window.ShowUtility();
        }

        private void OnGUI()
        {
            if (_data == null)
            {
                Close();
                return;
            }

            DrawHeader();
            DrawCountSummary();
            GUILayout.Space(8);
            _scroll = EditorGUILayout.BeginScrollView(_scroll);
            if (_data.Success)
            {
                DrawSummary();
                GUILayout.Space(8);
                DrawLogs();
            }
            else
            {
                DrawError();
                GUILayout.Space(8);
                DrawLogs();
                GUILayout.Space(8);
                DrawSummary();
            }

            EditorGUILayout.EndScrollView();
            GUILayout.Space(8);
            DrawButtons();
        }

        private void DrawHeader()
        {
            var rect = EditorGUILayout.BeginVertical(EditorStyles.helpBox);
            GUILayout.Space(6);
            var title = _data.Success ? EditorLocalize.Get(1038) : EditorLocalize.Get(1039);
            var style = new GUIStyle(EditorStyles.boldLabel)
            {
                fontSize = 18,
                alignment = TextAnchor.MiddleCenter,
                normal = { textColor = _data.Success ? new Color(0.2f, 0.65f, 0.25f) : new Color(0.85f, 0.25f, 0.2f) }
            };
            EditorGUILayout.LabelField(title, style, GUILayout.Height(30));
            GUILayout.Space(6);
            EditorGUILayout.EndVertical();
        }

        private void DrawCountSummary()
        {
            if (_data.SheetCount <= 0 && _data.GeneratedFileCount <= 0)
                return;
            var sb = new StringBuilder();
            if (_data.SheetCount > 0)
            {
                sb.Append(EditorLocalize.Get(1056));
                sb.Append('：');
                sb.Append(_data.SheetCount);
            }

            if (_data.GeneratedFileCount > 0)
            {
                if (sb.Length > 0)
                    sb.Append("    ");
                sb.Append(EditorLocalize.Get(1057));
                sb.Append('：');
                sb.Append(_data.GeneratedFileCount);
            }

            var style = new GUIStyle(EditorStyles.centeredGreyMiniLabel)
            {
                fontSize = 12
            };
            EditorGUILayout.LabelField(sb.ToString(), style, GUILayout.Height(20));
        }

        private void DrawSummary()
        {
            _showSummary = EditorGUILayout.Foldout(_showSummary, EditorLocalize.Get(1040), true);
            if (!_showSummary)
                return;
            DrawPath(EditorLocalize.Get(1041), _data.ExcelDir);
            DrawPath(EditorLocalize.Get(1042), _data.JsonExportDir);
            DrawPath(EditorLocalize.Get(1043), _data.CsharpExportDir);
            DrawPath(EditorLocalize.Get(1044), _data.OutputDir);
            DrawNumber(EditorLocalize.Get(1056), _data.SheetCount);
            DrawNumber(EditorLocalize.Get(1057), _data.GeneratedFileCount);
        }

        private void DrawNumber(string label, int value)
        {
            if (value <= 0)
                return;
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(label, GUILayout.Width(110));
            EditorGUILayout.SelectableLabel(value.ToString(), EditorStyles.textField,
                GUILayout.Height(EditorGUIUtility.singleLineHeight));
            EditorGUILayout.EndHorizontal();
        }

        private void DrawPath(string label, string path)
        {
            if (string.IsNullOrWhiteSpace(path))
                return;
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(label, GUILayout.Width(110));
            EditorGUILayout.SelectableLabel(path, EditorStyles.textField,
                GUILayout.Height(EditorGUIUtility.singleLineHeight));
            if (GUILayout.Button(EditorLocalize.Get(1045), GUILayout.Width(72)))
                Reveal(path);
            EditorGUILayout.EndHorizontal();
        }

        private void DrawError()
        {
            if (_data.Success)
                return;
            EditorGUILayout.LabelField(EditorLocalize.Get(1046), EditorStyles.boldLabel);
            var errorText = BuildErrorText();
            DrawScrollableText(string.IsNullOrWhiteSpace(errorText) ? EditorLocalize.Get(1047) : errorText,
                ref _errorScroll, 150);
        }

        private void DrawLogs()
        {
            _showLogs = EditorGUILayout.Foldout(_showLogs, EditorLocalize.Get(1048), true);
            if (!_showLogs)
                return;
            var logText = BuildLogText();
            DrawScrollableText(string.IsNullOrWhiteSpace(logText) ? EditorLocalize.Get(1049) : logText, ref _logScroll,
                220);
        }


        private static void DrawScrollableText(string text, ref Vector2 scroll, float height)
        {
            var style = new GUIStyle(EditorStyles.textArea)
            {
                wordWrap = true
            };
            scroll = EditorGUILayout.BeginScrollView(scroll, GUI.skin.box, GUILayout.Height(height));
            EditorGUILayout.TextArea(text ?? string.Empty, style, GUILayout.ExpandHeight(true));
            EditorGUILayout.EndScrollView();
        }

        private void DrawButtons()
        {
            EditorGUILayout.BeginHorizontal();
            if (_data.Success)
            {
                if (GUILayout.Button(EditorLocalize.Get(1050)))
                    Reveal(_data.JsonExportDir);
                if (GUILayout.Button(EditorLocalize.Get(1051)))
                    Reveal(_data.CsharpExportDir);
            }
            else
            {
                if (GUILayout.Button(EditorLocalize.Get(1052)))
                    Reveal(_data.ExcelDir);
                if (GUILayout.Button(EditorLocalize.Get(1053)))
                    GUIUtility.systemCopyBuffer = BuildErrorText();
            }

            if (GUILayout.Button(EditorLocalize.Get(1054)))
                GUIUtility.systemCopyBuffer = BuildReportText(_data);
            if (GUILayout.Button(EditorLocalize.Get(1010), GUILayout.Width(90)))
                Close();
            EditorGUILayout.EndHorizontal();
        }

        private string BuildErrorText()
        {
            return BuildErrorText(_data);
        }

        private string BuildLogText()
        {
            return BuildLogText(_data);
        }

        public static string BuildReportText(ReportData data)
        {
            if (data == null)
                return string.Empty;
            var sb = new StringBuilder();
            sb.AppendLine(data.Success ? EditorLocalize.Get(1038) : EditorLocalize.Get(1039));
            sb.AppendLine();
            AppendLabel(sb, EditorLocalize.Get(1041), data.ExcelDir);
            AppendLabel(sb, EditorLocalize.Get(1042), data.JsonExportDir);
            AppendLabel(sb, EditorLocalize.Get(1043), data.CsharpExportDir);
            AppendLabel(sb, EditorLocalize.Get(1044), data.OutputDir);
            AppendNumber(sb, EditorLocalize.Get(1056), data.SheetCount);
            AppendNumber(sb, EditorLocalize.Get(1057), data.GeneratedFileCount);
            var error = BuildErrorText(data);
            if (!string.IsNullOrWhiteSpace(error))
            {
                sb.AppendLine();
                sb.AppendLine(EditorLocalize.Get(1046));
                sb.AppendLine(error);
            }

            var logs = BuildLogText(data);
            if (!string.IsNullOrWhiteSpace(logs))
            {
                sb.AppendLine();
                sb.AppendLine(EditorLocalize.Get(1048));
                sb.AppendLine(logs);
            }

            return sb.ToString().Trim();
        }

        private static string BuildErrorText(ReportData data)
        {
            if (data == null)
                return string.Empty;
            var sb = new StringBuilder();
            AppendLine(sb, data.ErrorMessage);
            AppendLine(sb, data.ErrorDetail);
            foreach (var error in data.ErrorLogs)
                AppendLine(sb, error);
            return sb.ToString().Trim();
        }

        private static string BuildLogText(ReportData data)
        {
            if (data == null)
                return string.Empty;
            var sb = new StringBuilder();
            foreach (var info in data.InfoLogs)
                AppendLine(sb, info);
            if (data.ErrorLogs.Count > 0)
            {
                if (sb.Length > 0)
                    sb.AppendLine();
                sb.AppendLine(EditorLocalize.Get(1046));
                foreach (var error in data.ErrorLogs)
                    AppendLine(sb, error);
            }

            return sb.ToString().Trim();
        }

        private static void AppendLabel(StringBuilder sb, string label, string value)
        {
            if (string.IsNullOrWhiteSpace(value))
                return;
            sb.Append(label);
            sb.Append(' ');
            sb.AppendLine(value);
        }

        private static void AppendNumber(StringBuilder sb, string label, int value)
        {
            if (value <= 0)
                return;
            sb.Append(label);
            sb.Append(' ');
            sb.AppendLine(value.ToString());
        }

        private static void AppendLine(StringBuilder sb, string value)
        {
            if (string.IsNullOrWhiteSpace(value))
                return;
            if (sb.Length > 0)
                sb.AppendLine();
            sb.AppendLine(value.Trim());
        }

        private static void Reveal(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
                return;
            path = Path.GetFullPath(path);
            if (File.Exists(path) || Directory.Exists(path))
            {
                EditorUtility.RevealInFinder(path);
                return;
            }

            var dir = Path.GetDirectoryName(path);
            if (!string.IsNullOrEmpty(dir) && Directory.Exists(dir))
                EditorUtility.RevealInFinder(dir);
        }
    }
}