using System;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;

#if AR_NDMF
using nadena.dev.ndmf;
#endif

namespace AvatarRefinery.Editor.Core
{
    /// <summary>NDMF処理中に報告されたメッセージ(NDMF型に依存しない形)</summary>
    public sealed class NdmfMessage
    {
        /// <summary>"Information" / "NonFatal" / "Error" / "InternalError"</summary>
        public string Severity;
        public string Message;
    }

    /// <summary>
    /// NDMFで「ビルド後の姿」のクローンを作るアダプタ。
    /// 非破壊ツール(Modular Avatar / AAO 等)使用時、シーン上の数値はアップロード後と異なるため、
    /// 性能算定はこのクローンに対して行う。オリジナルには一切触れない。
    /// NDMFのエラー報告は ErrorReport.CaptureErrors で横取りし(NDMFコンソールを自動表示させない)、診断結果として保持する。
    /// </summary>
    public sealed class BakedAvatar : IDisposable
    {
        public GameObject Root { get; private set; }
        public bool Ok { get; private set; }
        public string Error { get; private set; }
        public long ElapsedMs { get; private set; }
        public List<NdmfMessage> Messages { get; } = new List<NdmfMessage>();

        private BakedAvatar() { }

        public static bool Available
        {
            get
            {
#if AR_NDMF
                return true;
#else
                return false;
#endif
            }
        }

        /// <summary>クローンを作りNDMFで処理する。失敗時は Ok=false、Root=null。</summary>
        public static BakedAvatar Create(GameObject original)
        {
            var b = new BakedAvatar();
#if AR_NDMF
            var sw = System.Diagnostics.Stopwatch.StartNew();
            GameObject clone = null;
            try
            {
                if (!AvatarProcessor.CanProcessObject(original))
                {
                    b.Ok = false; b.Error = L10n.T("NDMFが処理できる形式ではありません(VRC Avatar Descriptor が無い等)", "NDMF cannot process this avatar (for example, VRC Avatar Descriptor may be missing)");
                    return b;
                }
                clone = Object.Instantiate(original);
                clone.name = original.name + " (AvatarRefinery bake)";
                clone.hideFlags = HideFlags.HideAndDontSave;
                clone.transform.position += Vector3.right * 5f;

                Exception processError = null;
                var captured = ErrorReport.CaptureErrors(() =>
                {
                    try { AvatarProcessor.ProcessAvatar(clone); }
                    catch (Exception e) { processError = e; throw; }
                });
                foreach (var c in captured)
                {
                    try
                    {
                        b.Messages.Add(new NdmfMessage
                        {
                            Severity = c.TheError?.Severity.ToString() ?? "Error",
                            Message = c.TheError?.ToMessage() ?? "(unknown)",
                        });
                    }
                    catch { /* メッセージ整形の失敗は無視 */ }
                }
                if (processError != null) throw processError;

                b.Root = clone; b.Ok = true;
            }
            catch (Exception e)
            {
                b.Ok = false; b.Error = e.GetType().Name + ": " + e.Message;
                if (clone != null) Object.DestroyImmediate(clone);
            }
            finally { b.ElapsedMs = sw.ElapsedMilliseconds; }
#else
            b.Ok = false; b.Error = "NDMF not present";
#endif
            return b;
        }

        public void Dispose()
        {
            if (Root != null) { Object.DestroyImmediate(Root); Root = null; }
#if AR_NDMF
            try { AvatarProcessor.CleanTemporaryAssets(); }
            catch (Exception e) { Debug.LogWarning("[AvatarRefinery] Failed to clean NDMF temporary assets: " + e.Message); }
#endif
        }
    }
}
