using System.Collections.Generic;
using System.Text;

namespace TD.Levels.Editor
{
    /// <summary>
    /// Accumulates errors and warnings produced during a bake run. Phases append to the report
    /// and can check <see cref="HasErrors"/> at phase boundaries to decide whether to abort.
    /// </summary>
    /// <remarks>
    /// The bake never bails on the first error within a phase — all errors in a phase are
    /// collected before the phase reports back. A phase boundary is the place where the pipeline
    /// checks <see cref="HasErrors"/> and decides whether to continue or abort.
    /// </remarks>
    public class BakeReport
    {
        private readonly List<string> _errors = new List<string>();
        private readonly List<string> _warnings = new List<string>();

        /// <summary>Errors collected so far. Hard-error phases abort the bake when this is non-empty.</summary>
        public IReadOnlyList<string> Errors => _errors;

        /// <summary>Warnings collected so far. Warnings never abort the bake.</summary>
        public IReadOnlyList<string> Warnings => _warnings;

        /// <summary>True if any hard errors have been recorded.</summary>
        public bool HasErrors => _errors.Count > 0;

        /// <summary>Total error count.</summary>
        public int ErrorCount => _errors.Count;

        /// <summary>Total warning count.</summary>
        public int WarningCount => _warnings.Count;

        /// <summary>Records a hard error. The check ID (e.g. "P2-1") is prefixed for traceability.</summary>
        public void Error(string checkId, string message)
        {
            _errors.Add($"[{checkId}] {message}");
        }

        /// <summary>Records a soft warning. The check ID (e.g. "P2-8") is prefixed for traceability.</summary>
        public void Warning(string checkId, string message)
        {
            _warnings.Add($"[{checkId}] {message}");
        }

        /// <summary>Records an error not associated with a numbered check (e.g. "phase 1 found null authoring").</summary>
        public void Error(string message)
        {
            _errors.Add(message);
        }

        /// <summary>Records a warning not associated with a numbered check (e.g. "thumbnail render failed").</summary>
        public void Warning(string message)
        {
            _warnings.Add(message);
        }

        /// <summary>Renders the full report as a human-readable string for console logging.</summary>
        public string Format()
        {
            var sb = new StringBuilder();
            if (_errors.Count > 0)
            {
                sb.AppendLine($"Errors ({_errors.Count}):");
                for (int i = 0; i < _errors.Count; i++)
                {
                    sb.AppendLine($"  • {_errors[i]}");
                }
            }
            if (_warnings.Count > 0)
            {
                sb.AppendLine($"Warnings ({_warnings.Count}):");
                for (int i = 0; i < _warnings.Count; i++)
                {
                    sb.AppendLine($"  • {_warnings[i]}");
                }
            }
            if (_errors.Count == 0 && _warnings.Count == 0)
            {
                sb.AppendLine("(no errors or warnings)");
            }
            return sb.ToString();
        }
    }
}
