using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.IO;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;

namespace UnityEditor.HiveEditor
{

    /// <summary>플러그인이 구현하는 클래스 방식 Post-Build Task 인터페이스.</summary>
    public interface IHivePostBuildTask
    {
        /// <remarks>낮을수록 먼저 실행됩니다.</remarks>
        int CallbackOrder { get; }

        /// <summary>Unity Player 빌드 완료 후 호출됩니다.</summary>
        void OnHivePostBuild(in HivePostBuildContext context);
    }


    static class HivePluginPathResolver
    {
        public static string GetPluginDeployPath(string targetPath)
        {
#if HIVE_SDK_LOAD_FROM_STREAMING_ASSETS
            return Path.Combine(HiveBuildUtility.Windows.GetBuildExternalSDKPath(targetPath), "plugins");
#else
            return Path.Combine(targetPath, "plugins");
#endif
        }
    }
    
    public class HivePostProcessForHivePlugins : IPostprocessBuildWithReport
    {
        /// <summary>
        /// Hive SDK PostBuild 이후 작동하도록 설정
        /// </summary>
        public int callbackOrder => UnityEditor.HiveEditor.HivePostProcess.HiveSDKPostBuildOrder + 1;

        /// <summary>
        /// Hive SDK 플러그인(리모트플레이 등) 후처리 작업을 수행합니다.
        /// HivePostBuildAttribute 를 호출하여 Hive SDK OnPostProcessBuild 이후 호출되는 것을 보장합니다.
        /// Plugin을 적절한 위치에 배치하기 위함입니다.
        /// </summary>
        /// <param name="target"></param>
        /// <param name="path"></param>
        public void OnPostprocessBuild(BuildReport report)
        {
            
            var buildOutputDir = Path.GetDirectoryName(report.summary.outputPath);

#if UNITY_STANDALONE_WIN
            var ctx = new HivePostBuildContext(
                        report.summary,
                        HivePluginPathResolver.GetPluginDeployPath(buildOutputDir));
#else
            var ctx = new HivePostBuildContext(report.summary);
#endif

            var tasks = UnityEditor.TypeCache
                         .GetMethodsWithAttribute<HivePostBuildAttribute>()
                         .Select(m => (m.GetCustomAttribute<HivePostBuildAttribute>().Order, m))
                         .OrderBy(t => t.Order);

            foreach (var (order, mi) in tasks)
            {
                try
                {
                    Invoke(mi, ctx);
                }
                catch (Exception ex)
                {
                    UnityEngine.Debug.LogError(
                        $"[HivePostBuild] {mi.DeclaringType}.{mi.Name} 실패 (order {order})\n{ex}");
                }
            }
        }

        static void Invoke(MethodInfo mi, HivePostBuildContext ctx)
        {
            var ps = mi.GetParameters();
            if (ps.Length == 0)
                mi.Invoke(null, null);
            else if (ps.Length == 1 && ps[0].ParameterType == typeof(HivePostBuildContext))
                mi.Invoke(null, new object[] { ctx });
            else
                UnityEngine.Debug.LogWarning(
                    $"[HivePostBuild] {mi.DeclaringType}.{mi.Name} 시그니처 불일치(무시).");
        }
    }
}