package httpapi

import (
	"sort"
	"strconv"
	"strings"

	"git.vakhrushev.me/av/jellybit/internal/layout"
	"git.vakhrushev.me/av/jellybit/internal/recognize"
)

// fileRow — строка виджета «файл источника → раскладка», общего для экранов
// ревью и просмотра загрузки. Целевой путь берётся из превью (единая логика
// internal/layout), а не вычисляется в шаблоне.
type fileRow struct {
	Src       string
	Dst       string // целевой путь; пусто — файл не раскладывается
	RoleLabel string
	Linked    bool
	Ignored   bool
}

// buildFileRows сшивает файлы плана с целевыми путями из превью раскладки.
func buildFileRows(plan recognize.Plan, preview []layout.Link) []fileRow {
	dstBySrc := make(map[string]string, len(preview))
	for _, l := range preview {
		dstBySrc[l.Src] = l.Dst
	}
	rows := make([]fileRow, 0, len(plan.Files))
	for _, f := range plan.Files {
		dst := dstBySrc[f.Src]
		rows = append(rows, fileRow{
			Src:       f.Src,
			Dst:       dst,
			RoleLabel: roleLabel(string(f.Role)),
			Linked:    dst != "",
			Ignored:   f.Role == "ignore",
		})
	}
	return rows
}

// seasonSummary собирает верхнеуровневую сводку сезонов сериальной раздачи по
// эпизодным файлам плана. Сезон задан на файле (мультисезонные паки), поэтому
// сводим множество различных сезонов; Season nil/0 — спецвыпуски. Примеры:
// «Сезон 2», «Сезоны 1–3», «Сезоны 1, 3–4», «Спецвыпуски», «Сезоны 1–2, спецвыпуски».
func seasonSummary(plan recognize.Plan) string {
	seen := map[int]bool{}
	specials := false
	for _, f := range plan.Files {
		if f.Role != recognize.RoleEpisode {
			continue
		}
		n := 0
		if f.Season != nil {
			n = *f.Season
		}
		if n <= 0 {
			specials = true
			continue
		}
		seen[n] = true
	}
	nums := make([]int, 0, len(seen))
	for n := range seen {
		nums = append(nums, n)
	}
	sort.Ints(nums)

	var parts []string
	switch {
	case len(nums) == 1:
		parts = append(parts, "Сезон "+strconv.Itoa(nums[0]))
	case len(nums) > 1:
		parts = append(parts, "Сезоны "+seasonRanges(nums))
	}
	if specials {
		if len(parts) == 0 {
			parts = append(parts, "Спецвыпуски")
		} else {
			parts = append(parts, "спецвыпуски")
		}
	}
	return strings.Join(parts, ", ")
}

// seasonRanges схлопывает возрастающие номера сезонов в диапазоны:
// [1,2,3] → «1–3», [1,3,4] → «1, 3–4».
func seasonRanges(nums []int) string {
	var out []string
	for i := 0; i < len(nums); {
		j := i
		for j+1 < len(nums) && nums[j+1] == nums[j]+1 {
			j++
		}
		if j == i {
			out = append(out, strconv.Itoa(nums[i]))
		} else {
			out = append(out, strconv.Itoa(nums[i])+"–"+strconv.Itoa(nums[j]))
		}
		i = j + 1
	}
	return strings.Join(out, ", ")
}

// roleLabel — человекочитаемая роль файла раскладки.
func roleLabel(role string) string {
	switch role {
	case "episode":
		return "эпизод"
	case "main", "movie":
		return "фильм"
	case "subtitle":
		return "субтитры"
	case "extra":
		return "допматериал"
	case "sample":
		return "семпл"
	case "ignore":
		return "игнор"
	default:
		return role
	}
}
