package report

import (
	"fmt"
	"strconv"
	"strings"

	"pinscrape-allgo/internal/config"
	"pinscrape-allgo/internal/db"
)

// Want selects which counters the scrape summary block shows. The block
// follows the workflow that ran: scrape only shows Images/Description/
// Related KW, AI steps add their own line.
type Want struct {
	Images      bool
	Description bool
	RelatedKW   bool
	AITitle     bool
	AIArticles  bool
}

// Scrape renders the scrape progress block aggregated over all databases:
//
//	Images : 97.000/100.000 (97%)
//	Description : 95.000/100.000 (95%)
func Scrape(cfg *config.Config, want Want) []string {
	files, err := db.ListDBFiles(cfg.Path(cfg.DataFolder))
	if err != nil {
		return nil
	}
	var total db.Progress
	for _, f := range files {
		conn, err := db.Open(f)
		if err != nil {
			continue
		}
		p, err := db.CountProgress(conn)
		db.Close(conn)
		if err != nil {
			continue
		}
		total.Total += p.Total
		total.Images += p.Images
		total.Descriptions += p.Descriptions
		total.Related += p.Related
		total.AITitles += p.AITitles
		total.AIArticles += p.AIArticles
	}

	var lines []string
	if want.Images {
		lines = append(lines, Line("Images", total.Images, total.Total))
	}
	if want.Description {
		lines = append(lines, Line("Description", total.Descriptions, total.Total))
	}
	if want.RelatedKW {
		lines = append(lines, Line("Related KW", total.Related, total.Total))
	}
	if want.AITitle {
		lines = append(lines, Line("AI Title", total.AITitles, total.Total))
	}
	if want.AIArticles {
		lines = append(lines, Line("AI Articles", total.AIArticles, total.Total))
	}
	return lines
}

// Line renders one counter as "Images : 97.000/100.000 (97%)": dot thousands
// separators and a percentage with at most one decimal.
func Line(label string, filled, total int64) string {
	return fmt.Sprintf("%s : %s/%s (%s%%)", label, dot(filled), dot(total), percent(filled, total))
}

// Folders renders the export line: "Export : 50 Folder".
func Folders(n int) string {
	return fmt.Sprintf("Export : %d Folder", n)
}

// Outcome renders a stage line: "Upload : SUCCESS 49, FAIL 1".
func Outcome(stage string, ok, fail int) string {
	return fmt.Sprintf("%s : SUCCESS %d, FAIL %d", stage, ok, fail)
}

// Separator is the divider between the scrape block and the deploy block in
// a combined full-auto summary.
const Separator = "------"

// dot formats n with dots as thousands separators (97 -> "97", 97000 ->
// "97.000").
func dot(n int64) string {
	s := strconv.FormatInt(n, 10)
	var out []byte
	for i, ch := range []byte(s) {
		if i > 0 && (len(s)-i)%3 == 0 {
			out = append(out, '.')
		}
		out = append(out, ch)
	}
	return string(out)
}

// percent renders filled/total as a percentage with one decimal, trailing
// ".0" trimmed ("97", "99.8", "100").
func percent(filled, total int64) string {
	if total <= 0 {
		return "0"
	}
	p := float64(filled) * 100 / float64(total)
	return strings.TrimSuffix(strconv.FormatFloat(p, 'f', 1, 64), ".0")
}
