using System;
using System.Collections.Generic;
using UnityEngine;

namespace AvatarRefinery.Editor.Core
{
    /// <summary>重要度。UI表示順・集計の単位。</summary>
    public enum Severity
    {
        /// <summary>⛔ アップロード/ビルドを止める、または確実に壊れる</summary>
        Blocker = 0,
        /// <summary>⚠ 見た目・動作がおかしくなる</summary>
        Broken = 1,
        /// <summary>📉 パフォーマンスランクを下げている</summary>
        Performance = 2,
        /// <summary>ℹ 情報・改善余地</summary>
        Info = 3,
    }

    /// <summary>問題が影響するプラットフォーム</summary>
    [Flags]
    public enum PlatformScope
    {
        None = 0,
        PC = 1,
        Android = 2,
        Both = PC | Android,
    }

    /// <summary>診断で見つかった1件の問題。ルールが生成し、UI・レポートが消費する。</summary>
    [Serializable]
    public sealed class Issue
    {
        /// <summary>ルールID(知識データのキー。例: "material.missing_shader")</summary>
        public string RuleId;
        public Severity Severity;
        public PlatformScope Platform = PlatformScope.Both;

        /// <summary>症状で書いた見出し(例: 「マテリアルがピンク色に表示されます」)。知識データの既定を上書きしたい時のみ設定。</summary>
        public string TitleOverride;

        /// <summary>この事例固有の検出内容(数値・対象名など)。知識データの汎用説明に続けて表示される。</summary>
        public string Detail;

        /// <summary>問題の対象。SceneのObject参照(オリジナル側)。ping/選択に使う。</summary>
        public List<UnityEngine.Object> Targets = new List<UnityEngine.Object>();

        /// <summary>対象の階層パス(Object参照が失われた後やレポート用)</summary>
        public List<string> TargetPaths = new List<string>();

        /// <summary>数値情報(レポート・Before/After比較用)。例: {"value": 158.5, "limit": 150}</summary>
        public Dictionary<string, string> Metrics = new Dictionary<string, string>();

        /// <summary>自動修正が可能か(Liteでは表示のみ、有料版で実行)</summary>
        public bool AutoFixable;

        /// <summary>この事例向けの追加ヒント(任意)。知識データの手順に追記される。</summary>
        public string ExtraHint;

        public Issue(string ruleId, Severity severity)
        {
            RuleId = ruleId;
            Severity = severity;
        }

        public Issue WithTarget(UnityEngine.Object target, Transform avatarRoot = null)
        {
            if (target == null) return this;
            Targets.Add(target);
            var t = target as Transform ?? (target as Component)?.transform ?? (target as GameObject)?.transform;
            TargetPaths.Add(t != null ? HierarchyPath(t, avatarRoot) : target.name);
            return this;
        }

        public Issue WithMetric(string key, object value)
        {
            Metrics[key] = value?.ToString() ?? "null";
            return this;
        }

        public static string HierarchyPath(Transform t, Transform root)
        {
            var parts = new List<string>();
            while (t != null && t != root) { parts.Add(t.name); t = t.parent; }
            if (t == root && root != null) parts.Add(root.name);
            parts.Reverse();
            return string.Join("/", parts);
        }
    }
}
