package browser

import (
	"strings"

	"github.com/PuerkitoBio/goquery"
)

// PageState is the compact return shape after a navigation action.
type PageState struct {
	URL                        string                    `json:"url"`
	Title                      string                    `json:"title"`
	MarkdownExcerpt            string                    `json:"markdown_excerpt"`
	InteractiveElementsSummary InteractiveElementsCounts `json:"interactive_elements_summary"`
}

// InteractiveElementsCounts summarizes clickable/typable elements on the page.
type InteractiveElementsCounts struct {
	Buttons int `json:"buttons"`
	Inputs  int `json:"inputs"`
	Links   int `json:"links"`
}

// maxPageStateHTMLBytes caps how much DOM we'll parse for the compact
// page_state summary. A 200MB DOM from a malicious page would otherwise
// OOM the builder before goquery even ran.
const maxPageStateHTMLBytes = 10 * 1024 * 1024

// BuildPageState fetches the current HTML and produces a compact PageState.
// excerptChars defaults to 500 when 0. Does NOT bump the action counter —
// it's called internally after navigation actions.
func (s *Session) BuildPageState(excerptChars int) (PageState, error) {
	if excerptChars == 0 {
		excerptChars = 500
	}
	url, _ := s.CurrentURL()
	html, err := s.getHTMLInternal()
	if err != nil {
		return PageState{URL: url}, err
	}
	if len(html) > maxPageStateHTMLBytes {
		html = html[:maxPageStateHTMLBytes]
	}
	doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))
	if err != nil {
		return PageState{URL: url}, err
	}
	title := strings.TrimSpace(doc.Find("title").First().Text())
	bodyText := strings.TrimSpace(doc.Find("body").Text())
	bodyText = strings.Join(strings.Fields(bodyText), " ")
	if len(bodyText) > excerptChars {
		bodyText = bodyText[:excerptChars] + "…"
	}
	return PageState{
		URL:             url,
		Title:           title,
		MarkdownExcerpt: bodyText,
		InteractiveElementsSummary: InteractiveElementsCounts{
			Buttons: doc.Find("button").Length(),
			Inputs:  doc.Find("input,textarea,select").Length(),
			Links:   doc.Find("a[href]").Length(),
		},
	}, nil
}
