// Asset Naming Manager — the History tab: every batch the Cop applied, and how to put it back.
using System.Collections.Generic;
using UnityEditor;
using UnityEngine.UIElements;

namespace AssetNamingManager.UI
{
    public partial class NamingManagerWindow
    {
        VisualElement BuildHistoryTab()
        {
            var batches = FixJournal.All();

            if (batches.Count == 0)
            {
                return BuildEmpty("d_UndoHistory", "Nothing fixed yet",
                    "Unity's own undo does not cover asset moves, so the Cop keeps its own journal. " +
                    "Every batch you apply is recorded here and can be put back, for the last twenty batches. " +
                    "The journal lives in UserSettings, which Unity's default gitignore already excludes.",
                    "anm-empty--neutral");
            }

            var scroll = new ScrollView();
            scroll.AddToClassList("anm-scroll");

            var root = new VisualElement();
            root.AddToClassList("anm-rules");

            var info = new VisualElement();
            info.AddToClassList("anm-info-box");
            var infoText = new Label(
                "Reverting moves every asset in a batch back to where it came from, newest change first. " +
                "Anything that has been renamed again since is skipped and reported rather than guessed at.");
            infoText.AddToClassList("anm-info-box__text");
            info.Add(infoText);
            root.Add(info);

            // Newest first reads better than the order they were recorded in.
            for (int i = batches.Count - 1; i >= 0; i--)
                root.Add(BuildHistoryRow(batches[i]));

            var footer = new VisualElement();
            footer.style.flexDirection = FlexDirection.Row;
            footer.style.marginTop = 8f;
            footer.Add(Spacer());
            footer.Add(MakeDangerButton("Clear history", () =>
            {
                bool ok = EditorUtility.DisplayDialog(
                    "Clear the fix journal?",
                    "This forgets every recorded batch, so none of them can be reverted afterwards.\n\n" +
                    "Your files are not touched — they stay exactly as they are now.",
                    "Clear journal", "Cancel");

                if (!ok) return;

                FixJournal.Clear();
                SetStatus("Fix journal cleared. Files were not changed.");
                ShowTab(Tab.History);
            }, "Forget every batch. Files are not changed."));
            root.Add(footer);

            scroll.Add(root);
            return scroll;
        }

        VisualElement BuildHistoryRow(FixJournal.Batch batch)
        {
            var row = new VisualElement();
            row.AddToClassList("anm-history-row");

            var main = new VisualElement();
            main.AddToClassList("anm-history-row__main");

            int renames = 0, moves = 0;
            foreach (var entry in batch.entries)
            {
                if (string.Equals(FixPlan.ParentFolder(entry.from), FixPlan.ParentFolder(entry.to),
                                  System.StringComparison.Ordinal)) renames++;
                else moves++;
            }

            var title = new Label(Describe(renames, moves));
            title.AddToClassList("anm-history-row__title");
            main.Add(title);

            var sub = new Label(batch.DisplayTime + "  ·  batch " + batch.id);
            sub.AddToClassList("anm-history-row__sub");
            main.Add(sub);

            row.Add(main);

            row.Add(MakeButton("Show", () =>
            {
                var lines = new List<string>();
                int shown = 0;
                foreach (var entry in batch.entries)
                {
                    if (shown++ >= 40) { lines.Add("… and " + (batch.entries.Count - 40) + " more"); break; }
                    lines.Add(NamingScanner.GetFileName(entry.from) + "  →  " + NamingScanner.GetFileName(entry.to));
                }

                EditorUtility.DisplayDialog("Batch " + batch.id,
                    string.Join("\n", lines.ToArray()), "Close");
            }, "List what this batch changed."));

            row.Add(MakeDangerButton("Revert", () =>
            {
                bool ok = EditorUtility.DisplayDialog(
                    "Revert this batch?",
                    "This moves " + batch.entries.Count + " assets back to their original names and folders.\n\n" +
                    "References survive, exactly as they did on the way out.",
                    "Revert " + batch.entries.Count + " assets", "Cancel");

                if (!ok) return;

                var problems = new List<string>();
                int restored = FixJournal.Revert(batch, problems);

                if (problems.Count > 0)
                {
                    foreach (var problem in problems)
                        UnityEngine.Debug.LogWarning(NamingManagerAbout.LogPrefix + problem);
                }

                SetStatus(restored + " assets put back" +
                          (problems.Count > 0 ? ", " + problems.Count + " could not be — see the Console" : "") + ".");
                Scan();
            }, "Move every asset in this batch back where it came from."));

            return row;
        }

        static string Describe(int renames, int moves)
        {
            if (renames > 0 && moves > 0) return renames + " renamed, " + moves + " moved";
            if (moves > 0) return moves + (moves == 1 ? " asset moved" : " assets moved");
            return renames + (renames == 1 ? " asset renamed" : " assets renamed");
        }
    }
}
