package renderer

import (
	"bufio"
	"fmt"
	"strings"
)

// Tag defines supported template blocks.
type Tag string

const (
	TagSpacer   Tag = "spacer"
	TagTitle    Tag = "title"
	TagSubtitle Tag = "subtitle"
	TagMeta     Tag = "meta"
	TagSection  Tag = "section"
	TagText     Tag = "text"
	TagKV       Tag = "kv"
	TagTable    Tag = "table"
	TagSign     Tag = "sign"
)

// Block represents a tagged content block extracted from template output.
type Block struct {
	Tag   Tag
	Lines []string
	Rows  [][]string
}

// ParseBlocks converts tagged template output into structured blocks.
func ParseBlocks(input string) ([]Block, error) {
	scanner := bufio.NewScanner(strings.NewReader(input))
	blocks := make([]Block, 0)

	var current *Block

	flush := func() {
		if current != nil {
			blocks = append(blocks, *current)
			current = nil
		}
	}

	for scanner.Scan() {
		line := strings.TrimRight(scanner.Text(), "\r")
		trimmed := strings.TrimSpace(line)

		if strings.HasPrefix(trimmed, "#") {
			flush()

			tag := Tag(strings.TrimSpace(strings.TrimPrefix(trimmed, "#")))

			if tag == "" {
				continue
			}

			if tag == TagSpacer {
				blocks = append(blocks, Block{Tag: TagSpacer})

				continue
			}

			current = &Block{Tag: tag}

			continue
		}

		if current == nil {
			continue
		}

		switch current.Tag { //nolint:exhaustive // only KV and Table need row parsing
		case TagKV, TagTable:
			if trimmed == "" {
				continue
			}

			parts := strings.Split(line, "|")

			row := make([]string, 0, len(parts))
			for _, part := range parts {
				row = append(row, strings.TrimSpace(part))
			}

			current.Rows = append(current.Rows, row)
		default:
			current.Lines = append(current.Lines, line)
		}
	}

	if err := scanner.Err(); err != nil {
		return nil, fmt.Errorf("parse blocks: %w", err)
	}

	flush()

	return blocks, nil
}
