package catalog

import (
	"bufio"
	"fmt"
	"rubric/utils"
	"strconv"
	"strings"
)

// Book описывает один справочник верхнего уровня
type Book struct {
	Key         string
	Aliases     []string
	Title       string
	Description string
	Run         func(scanner *bufio.Scanner) // передаём scanner чтобы не создавать новый
}

// All — список всех справочников
var All = []Book{
	GoBook,
	LinuxBook,
	DevOpsBook,
	InfoSecBook,
}

// Find ищет книгу по ключу или алиасу
func Find(key string) (Book, bool) {
	key = strings.ToLower(strings.TrimSpace(key))
	for _, b := range All {
		if b.Key == key {
			return b, true
		}
		for _, a := range b.Aliases {
			if a == key {
				return b, true
			}
		}
	}
	return Book{}, false
}

// ShowMainMenu отображает главное меню
func ShowMainMenu() {
	utils.Header("rubric — интерактивный справочник")

	fmt.Printf("  %s%sДоступные справочники:%s\n\n",
		utils.ColorBold, utils.ColorWhite, utils.ColorReset)

	for i, b := range All {
		aliases := ""
		if len(b.Aliases) > 0 {
			aliases = fmt.Sprintf("%s  [%s]%s",
				utils.ColorDim, strings.Join(b.Aliases, ", "), utils.ColorReset)
		}
		fmt.Printf("  %s%s %2d.%s  %s%-8s%s  %s%-34s%s%s\n",
			utils.ColorBold, utils.ColorCyan, i+1, utils.ColorReset,
			utils.ColorYellow+utils.ColorBold, b.Key, utils.ColorReset,
			utils.ColorWhite, b.Title, utils.ColorReset,
			aliases,
		)
		fmt.Printf("        %s%s%s\n\n",
			utils.ColorDim, b.Description, utils.ColorReset)
	}

	fmt.Printf("  %s%sВыберите справочник (номер / ключ / q — выход):%s ",
		utils.ColorBold, utils.ColorGreen, utils.ColorReset)
}

// RunInteractive — главный интерактивный цикл (алиас)
func RunInteractive(scanner *bufio.Scanner) {
	RunInteractiveWithSearch(scanner)
}

// RunInteractiveWithSearch — главный цикл с поддержкой поиска
func RunInteractiveWithSearch(scanner *bufio.Scanner) {
	for {
		ShowMainMenu()

		if !scanner.Scan() {
			break
		}
		input := strings.TrimSpace(scanner.Text())

		if input == "" {
			continue
		}
		if input == "q" || input == "quit" || input == "exit" {
			fmt.Printf("\n  %s%sДо свидания!%s\n\n",
				utils.ColorBold, utils.ColorCyan, utils.ColorReset)
			return
		}

		// Поиск: /ansible или search ansible
		query := ""
		if strings.HasPrefix(input, "/") {
			query = strings.TrimSpace(input[1:])
		} else if strings.HasPrefix(strings.ToLower(input), "search ") {
			query = strings.TrimSpace(input[7:])
		} else if strings.ToLower(input) == "search" {
			fmt.Printf("\n  %s%sВведите поисковый запрос:%s ", utils.ColorBold, utils.ColorGreen, utils.ColorReset)
			if scanner.Scan() {
				query = strings.TrimSpace(scanner.Text())
			}
		}

		if query != "" {
			results := Search(query)
			ShowSearchResults(query, results)
			if len(results) > 0 {
				fmt.Printf("  %s%sВведите номер раздела чтобы открыть (Enter — назад в меню):%s ",
					utils.ColorBold, utils.ColorGreen, utils.ColorReset)
				if scanner.Scan() {
					choice := strings.TrimSpace(scanner.Text())
					if n, err := strconv.Atoi(choice); err == nil && n >= 1 && n <= len(results) {
						fmt.Println()
						results[n-1].RunFunc()
						fmt.Printf("\n  %s%s[Enter — вернуться в меню]%s ", utils.ColorDim, utils.ColorCyan, utils.ColorReset)
						scanner.Scan()
					}
				}
			}
			continue
		}

		// По номеру
		if n, err := strconv.Atoi(input); err == nil {
			if n >= 1 && n <= len(All) {
				All[n-1].Run(scanner)
				continue
			}
			fmt.Printf("\n  %s%sНомер %d вне диапазона (1–%d)%s\n",
				utils.ColorBold, utils.ColorRed, n, len(All), utils.ColorReset)
			continue
		}

		// По ключу справочника
		if b, ok := Find(input); ok {
			b.Run(scanner)
			continue
		}

		fmt.Printf("\n  %s%sНе понял '%s'. Номер, ключ справочника, /запрос для поиска.%s\n",
			utils.ColorBold, utils.ColorRed, input, utils.ColorReset)
	}
}

// ShowHelp — общая справка
func ShowHelp() {
	utils.Header("rubric — справка по использованию")

	utils.Section("Запуск")
	utils.Command("./rubric", "главное меню")
	utils.Command("./rubric -book go", "открыть справочник")
	utils.Command("./rubric -book go -topic basics", "открыть конкретный раздел")
	utils.Command("./rubric -search ansible", "поиск по всем справочникам")
	utils.Command("./rubric -search 'sql injection'", "поиск по нескольким словам")
	utils.Command("./rubric -list", "список всех справочников и разделов")
	utils.Command("./rubric -help", "эта справка")
	fmt.Println()

	utils.Section("Поиск в интерактивном режиме")
	utils.Command("/ansible", "поиск по запросу (начать с /)")
	utils.Command("search nmap", "поиск командой search")
	utils.Command("search", "поиск (запросит строку)")
	fmt.Println()

	utils.Section("Доступные справочники")
	for _, b := range All {
		keys := append([]string{b.Key}, b.Aliases...)
		fmt.Printf("  %s%s%-8s%s  %-34s  %sключи: %s%s\n",
			utils.ColorBold, utils.ColorCyan, b.Key, utils.ColorReset,
			b.Title,
			utils.ColorDim, strings.Join(keys, ", "), utils.ColorReset,
		)
	}

	utils.Footer()
}

// ListAll — краткий список всех справочников и их разделов
func ListAll() {
	fmt.Printf("\n%s%srubric — все справочники:%s\n\n",
		utils.ColorBold, utils.ColorCyan, utils.ColorReset)

	for i, b := range All {
		fmt.Printf("  %s%d.%s %s%s%s — %s\n",
			utils.ColorDim, i+1, utils.ColorReset,
			utils.ColorYellow+utils.ColorBold, b.Key, utils.ColorReset,
			b.Title,
		)
	}
	fmt.Println()
}

// PrintBackPrompt — подсказка "вернуться назад"
func PrintBackPrompt(scanner *bufio.Scanner) {
	fmt.Printf("\n  %s%s[Enter — вернуться в меню справочника, b — главное меню]%s ",
		utils.ColorDim, utils.ColorCyan, utils.ColorReset)
	if scanner.Scan() {
		text := strings.TrimSpace(scanner.Text())
		_ = text // "b" обрабатывается в вызывающем коде
	}
}

// ReadLine читает строку из сканера
func ReadLine(scanner *bufio.Scanner) (string, bool) {
	if !scanner.Scan() {
		return "", false
	}
	return strings.TrimSpace(scanner.Text()), true
}

// IsBack возвращает true если пользователь хочет вернуться на уровень выше
func IsBack(s string) bool {
	return s == "b" || s == "back" || s == "назад" || s == ".."
}

// IsQuit возвращает true если пользователь хочет выйти
func IsQuit(s string) bool {
	return s == "q" || s == "quit" || s == "exit"
}
