// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package main

import (
	"regexp"
	"strings"

	"github.com/microcosm-cc/bluemonday"
)

var numberedListRegex = regexp.MustCompile(`^\d+\.\s`)

func formatBody(body string) (string, error) {
	p := bluemonday.UGCPolicy()
	sanitized := p.Sanitize(body)

	lines := strings.Split(sanitized, "\n")
	var result []string

	for _, line := range lines {
		trimmed := strings.TrimSpace(line)
		if trimmed == "" {
			result = append(result, "")
			continue
		}

		if strings.HasPrefix(trimmed, "- ") || strings.HasPrefix(trimmed, "* ") {
			marker := trimmed[:2]
			content := trimmed[2:]
			wrapped := wrapWithHangingIndent(marker, "  ", content, 72)
			result = append(result, wrapped)
			continue
		}

		if numberedListRegex.MatchString(trimmed) {
			parts := strings.SplitN(trimmed, " ", 2)
			marker := parts[0] + " "
			content := ""
			if len(parts) > 1 {
				content = parts[1]
			}
			indent := strings.Repeat(" ", len(marker))
			wrapped := wrapWithHangingIndent(marker, indent, content, 72)
			result = append(result, wrapped)
			continue
		}

		result = append(result, wordWrap(trimmed, 72))
	}

	return strings.Join(result, "\n"), nil
}

func wrapWithHangingIndent(firstPrefix, contPrefix, text string, width int) string {
	firstWidth := width - len(firstPrefix)
	contWidth := width - len(contPrefix)

	words := strings.Fields(text)
	if len(words) == 0 {
		return firstPrefix
	}

	var lines []string
	var currentLine strings.Builder
	var currentWidth int
	isFirstLine := true

	for _, word := range words {
		wordLen := len(word)
		maxWidth := firstWidth
		if !isFirstLine {
			maxWidth = contWidth
		}

		if currentLine.Len() == 0 {
			currentLine.WriteString(word)
			currentWidth = wordLen
		} else if currentWidth+1+wordLen <= maxWidth {
			currentLine.WriteString(" ")
			currentLine.WriteString(word)
			currentWidth += 1 + wordLen
		} else {
			if isFirstLine {
				lines = append(lines, firstPrefix+currentLine.String())
				isFirstLine = false
			} else {
				lines = append(lines, contPrefix+currentLine.String())
			}
			currentLine.Reset()
			currentLine.WriteString(word)
			currentWidth = wordLen
		}
	}

	if currentLine.Len() > 0 {
		if isFirstLine {
			lines = append(lines, firstPrefix+currentLine.String())
		} else {
			lines = append(lines, contPrefix+currentLine.String())
		}
	}

	return strings.Join(lines, "\n")
}

func wordWrap(text string, width int) string {
	words := strings.Fields(text)
	if len(words) == 0 {
		return ""
	}

	var result strings.Builder
	var currentLine strings.Builder
	var currentWidth int

	for _, word := range words {
		wordLen := len(word)

		if currentLine.Len() == 0 {
			currentLine.WriteString(word)
			currentWidth = wordLen
		} else if currentWidth+1+wordLen <= width {
			currentLine.WriteString(" ")
			currentLine.WriteString(word)
			currentWidth += 1 + wordLen
		} else {
			if result.Len() > 0 {
				result.WriteString("\n")
			}
			result.WriteString(currentLine.String())
			currentLine.Reset()
			currentLine.WriteString(word)
			currentWidth = wordLen
		}
	}

	if currentLine.Len() > 0 {
		if result.Len() > 0 {
			result.WriteString("\n")
		}
		result.WriteString(currentLine.String())
	}

	return result.String()
}
