using System.Text;
using System.Text.RegularExpressions;
using ClaudeDo.Data.Models;

namespace ClaudeDo.Worker.Runner;

public static class CommitMessageBuilder
{
    public static string Build(string commitType, string listName, string taskTitle, string? taskDescription, string taskId)
    {
        var slug = ToSlug(listName);
        var title = Truncate(taskTitle, 60);
        var header = $"{commitType}({slug}): {title}";

        var sb = new StringBuilder();
        sb.Append(header);

        var hasDescription = !string.IsNullOrWhiteSpace(taskDescription);
        if (hasDescription)
        {
            sb.Append("\n\n");
            sb.Append(Truncate(taskDescription!.Trim(), 400));
        }

        // Trailer is always included.
        sb.Append("\n\n");
        sb.Append($"ClaudeDo-Task: {taskId}");

        return sb.ToString();
    }

    /// <summary>
    /// Message for the merge commit that lands a task branch. Same Conventional-Commits header
    /// shape as the task's own commits (<see cref="Build"/>) with an explicit `merge ` verb, so
    /// merge commits stay parseable *and* greppable, plus the task-id trailer. A blank commit
    /// type falls back to <see cref="CommitTypeRegistry.DefaultType"/>; a list name that slugs
    /// to nothing drops the scope rather than emitting an empty `()`.
    /// </summary>
    public static string BuildMerge(string commitType, string listName, string taskTitle, string taskId)
    {
        var type = string.IsNullOrWhiteSpace(commitType) ? CommitTypeRegistry.DefaultType : commitType.Trim();
        var slug = ToSlug(listName);
        var scope = slug.Length == 0 ? "" : $"({slug})";
        var title = Truncate(taskTitle.Trim(), 60);

        return $"{type}{scope}: merge {title}\n\nClaudeDo-Task: {taskId}";
    }

    public static string ToSlug(string name)
    {
        var lower = name.ToLowerInvariant();
        // Replace whitespace runs with a single dash.
        var dashed = Regex.Replace(lower, @"\s+", "-");
        // Remove all non-alphanumeric-and-dash characters.
        var cleaned = Regex.Replace(dashed, @"[^a-z0-9\-]", "");
        // Collapse multiple dashes.
        var collapsed = Regex.Replace(cleaned, @"-{2,}", "-");
        // Trim leading/trailing dashes.
        return collapsed.Trim('-');
    }

    private static string Truncate(string value, int maxLength) =>
        value.Length <= maxLength ? value : value[..maxLength];
}
