// Asset Naming Manager — the Dashboard tab: health score, severity split, worst offenders.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

namespace AssetNamingManager.UI
{
    public partial class NamingManagerWindow
    {
        VisualElement BuildDashboardTab()
        {
            if (_report == null)
            {
                var empty = BuildEmpty("d_Search Icon", "Nothing to chart yet",
                    "Run a scan and this becomes a health score, a severity split, and a list of the " +
                    "rules and folders doing the most damage.", null);

                var actions = new VisualElement();
                actions.AddToClassList("anm-empty__actions");
                actions.Add(MakeButton("Scan", Scan, null, true));
                empty.Add(actions);
                return empty;
            }

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

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

            dash.Add(BuildHealthCard());
            dash.Add(BuildSeverityCard());
            dash.Add(BuildOffendersCard());
            dash.Add(BuildStatStrip());

            scroll.Add(dash);
            return scroll;
        }

        VisualElement BuildHealthCard()
        {
            var card = new CardElement("Health score", "weighted by severity against everything scanned");
            card.AddToClassList("anm-card--center");
            card.style.width = 226f;

            var gauge = new GaugeElement();
            gauge.Value = _report.HealthScore;
            gauge.Caption = _report.HealthLabel.ToUpperInvariant();
            card.body.Add(gauge);

            return card;
        }

        VisualElement BuildSeverityCard()
        {
            var card = new CardElement("Severity split", _report.violations.Count + " findings");
            card.AddToClassList("anm-card--center");
            card.style.width = 226f;

            var donut = new DonutElement();
            donut.SetSlices(new[]
            {
                new DonutSlice("Errors",   _report.ErrorCount,   NamingManagerTheme.Error),
                new DonutSlice("Warnings", _report.WarningCount, NamingManagerTheme.Warning),
                new DonutSlice("Info",     _report.InfoCount,    NamingManagerTheme.Info)
            }, "findings");
            card.body.Add(donut);

            var legend = new VisualElement();
            legend.AddToClassList("anm-legend");
            legend.Add(BuildLegendRow("Errors", _report.ErrorCount, NamingSeverity.Error));
            legend.Add(BuildLegendRow("Warnings", _report.WarningCount, NamingSeverity.Warning));
            legend.Add(BuildLegendRow("Info", _report.InfoCount, NamingSeverity.Info));
            card.body.Add(legend);

            return card;
        }

        VisualElement BuildLegendRow(string label, int count, NamingSeverity severity)
        {
            var row = new VisualElement();
            row.AddToClassList("anm-legend__row");
            row.tooltip = "Show only " + label + " in the Report tab.";

            var swatch = new VisualElement();
            swatch.AddToClassList("anm-legend__swatch");
            swatch.AddToClassList("anm-legend__swatch--" + NamingManagerTheme.ClassFor(severity));
            row.Add(swatch);

            var text = new Label(label);
            text.AddToClassList("anm-legend__label");
            row.Add(text);

            var value = new Label(count.ToString());
            value.AddToClassList("anm-legend__value");
            row.Add(value);

            // A dashboard that cannot be clicked is a dead end. Clicking a legend row filters the report.
            row.RegisterCallback<ClickEvent>(evt =>
            {
                _severityMask = severity == NamingSeverity.Error ? 4 : severity == NamingSeverity.Warning ? 2 : 1;
                NamingManagerSettings.SeverityMask = _severityMask;
                _search = string.Empty;
                ShowTab(Tab.Report);
            });

            return row;
        }

        VisualElement BuildOffendersCard()
        {
            var card = new CardElement("Worst offenders", "start here — one folder usually explains half the report");
            card.AddToClassList("anm-card--grow");

            AddBarBlock(card.body, "Findings per rule",
                ScanReport.Sorted(_report.CountBy(v => string.IsNullOrEmpty(v.ruleName) ? "Project-wide" : v.ruleName), 6),
                "anm-bar__fill--s0", GroupMode.Rule);

            AddBarBlock(card.body, "Findings per problem",
                ScanReport.Sorted(_report.CountBy(v => v.KindLabel), 6), "anm-bar__fill--s1", GroupMode.Problem);

            AddBarBlock(card.body, "Worst folders",
                ScanReport.Sorted(_report.CountBy(v => v.Directory), 6), "anm-bar__fill--s2", GroupMode.Folder);

            return card;
        }

        void AddBarBlock(VisualElement parent, string title, List<KeyValuePair<string, int>> rows,
                         string fillClass, GroupMode jumpTo)
        {
            if (rows.Count == 0) return;

            var heading = new Label(title);
            heading.AddToClassList("anm-card__title");
            heading.style.marginTop = parent.childCount > 0 ? 12f : 0f;
            parent.Add(heading);

            int max = 1;
            foreach (var row in rows) if (row.Value > max) max = row.Value;

            foreach (var row in rows)
            {
                var bar = new BarRow(ShortenKey(row.Key), row.Value, max, fillClass, row.Key);
                string key = row.Key;

                bar.RegisterCallback<ClickEvent>(evt =>
                {
                    _group = jumpTo;
                    NamingManagerSettings.GroupMode = _group;
                    _search = key == "Project-wide" ? string.Empty : key;
                    _severityMask = 7;
                    NamingManagerSettings.SeverityMask = _severityMask;
                    ShowTab(Tab.Report);
                });

                parent.Add(bar);
            }
        }

        static string ShortenKey(string key)
        {
            if (string.IsNullOrEmpty(key)) return "(none)";
            if (key.StartsWith("Assets/", System.StringComparison.Ordinal) && key.Length > 7)
                return key.Substring(7);
            return key;
        }

        VisualElement BuildStatStrip()
        {
            var strip = new VisualElement();
            strip.AddToClassList("anm-stats");

            strip.Add(new StatTile("assets scanned", _report.assetsScanned.ToString()));
            strip.Add(new StatTile("folders", _report.foldersScanned.ToString()));
            strip.Add(new StatTile("affected assets", _report.AffectedAssetCount.ToString()));
            strip.Add(new StatTile("auto-fixable", _report.AutoFixableCount.ToString(), "anm-stat__value--good",
                "Findings the Cop can correct without asking you anything else."));
            strip.Add(new StatTile("scan time", _report.durationSeconds.ToString("0.00") + "s"));

            if (_report.assetsIgnored > 0)
                strip.Add(new StatTile("ignored by glob", _report.assetsIgnored.ToString(), null,
                    "Third-party and excluded folders never appear in the report."));

            return strip;
        }
    }
}
