package toc

import (
	"fmt"
	"html"
	"regexp"
	"strings"
	"unicode/utf8"
)

var htmlTagRegexp = regexp.MustCompile(`<[^>]*>`)

// htmlTextLength 计算剥离 HTML 标签后的字符数，匹配 Telegram 的计数方式
func htmlTextLength(s string) int {
	stripped := htmlTagRegexp.ReplaceAllString(s, "")
	return utf8.RuneCountInString(stripped)
}

// renderLines 将所有分类和条目渲染为独立的行
func (m *Manager) renderLines() (header string, lines []string, footer string, err error) {
	categories, err := m.storage.ListCategories()
	if err != nil {
		return "", nil, "", err
	}

	entriesByCategory, err := m.storage.GetEntriesByCategory()
	if err != nil {
		return "", nil, "", err
	}

	header = "📚 <b>频道目录</b>\n━━━━━━━━━━━━━━━\n\n"
	footer = "━━━━━━━━━━━━━━━\n"

	if len(categories) == 0 {
		lines = append(lines, "<i>暂无分类</i>\n")
		return header, lines, footer, nil
	}

	for _, cat := range categories {
		entries := entriesByCategory[cat.Name]

		catLine := fmt.Sprintf("📁 <b>%s</b>", html.EscapeString(cat.Name))
		if len(entries) > 0 {
			catLine += fmt.Sprintf(" (%d)", len(entries))
		}
		catLine += "\n"
		lines = append(lines, catLine)

		if len(entries) == 0 {
			lines = append(lines, "   <i>暂无内容</i>\n")
		} else {
			for _, entry := range entries {
				entryLine := fmt.Sprintf("   • <a href=\"%s\">%s</a>", html.EscapeString(entry.MessageLink()), html.EscapeString(entry.Title))
				if entry.HasDirectLink() {
					entryLine += fmt.Sprintf(" <a href=\"%s\">[直达]</a>", html.EscapeString(entry.DirectLink))
				}
				entryLine += "\n"
				lines = append(lines, entryLine)
			}
		}

		// 分类之间空行
		lines = append(lines, "\n")
	}

	return header, lines, footer, nil
}

// RenderPage 渲染指定页的 TOC 内容，返回内容、总页数
func (m *Manager) RenderPage(page, charLimit int) (string, int, error) {
	header, lines, footer, err := m.renderLines()
	if err != nil {
		return "", 0, err
	}

	// 页码行的最大长度预估（如 "📄 99 / 99\n"）
	pageIndicatorLen := 15

	headerLen := htmlTextLength(header)
	footerLen := htmlTextLength(footer)
	fixedLen := headerLen + footerLen + pageIndicatorLen

	// 将行分配到各页
	var pages [][]string
	var currentPage []string
	currentLen := fixedLen

	for _, line := range lines {
		lineLen := htmlTextLength(line)

		// 如果当前页加上这行会超限，且当前页已有内容，则开新页
		if currentLen+lineLen > charLimit && len(currentPage) > 0 {
			pages = append(pages, currentPage)
			currentPage = nil
			currentLen = fixedLen
		}

		currentPage = append(currentPage, line)
		currentLen += lineLen
	}

	// 最后一页
	if len(currentPage) > 0 {
		pages = append(pages, currentPage)
	}

	totalPages := len(pages)
	if totalPages == 0 {
		totalPages = 1
		pages = [][]string{{}}
	}

	// clamp page
	if page < 1 {
		page = 1
	}
	if page > totalPages {
		page = totalPages
	}

	// 组装当前页内容
	var sb strings.Builder
	sb.WriteString(header)
	for _, line := range pages[page-1] {
		sb.WriteString(line)
	}
	sb.WriteString(footer)

	if totalPages > 1 {
		sb.WriteString(fmt.Sprintf("📄 %d / %d\n", page, totalPages))
	}

	return sb.String(), totalPages, nil
}

// Render 渲染完整 TOC（兼容方法，返回第 1 页，使用 photo caption 限制）
func (m *Manager) Render() (string, error) {
	content, _, err := m.RenderPage(1, captionCharLimit)
	return content, err
}
