package main

import (
	"fmt"
	"sort"
	"strings"
)

// ChannelList renders the channel sidebar for a server.
func ChannelList(channels []Channel, activeIdx, hoverIdx, width, height int) string {
	if len(channels) == 0 {
		return ChannelListStyle.
			Width(width).
			Height(height).
			Render(HelpStyle.Render("  No channels"))
	}

	// Group channels by category
	type catGroup struct {
		name     string
		channels []Channel
	}
	catOrder := make([]string, 0)
	catMap := make(map[string]*catGroup)

	for _, ch := range channels {
		cat := ch.Category
		if cat == "" {
			cat = "general"
		}
		if _, ok := catMap[cat]; !ok {
			catMap[cat] = &catGroup{name: cat}
			catOrder = append(catOrder, cat)
		}
		catMap[cat].channels = append(catMap[cat].channels, ch)
	}

	// Stable sort categories
	sort.Strings(catOrder)

	// Build flat list for index mapping
	var lines []string
	flatIdx := 0

	for _, catName := range catOrder {
		group := catMap[catName]
		lines = append(lines, CategoryStyle.Render(strings.ToUpper(group.name)))

		for _, ch := range group.channels {
			prefix := "  "
			if ch.Type == "voice" {
				prefix = VoiceChannelPrefix.Render("🔊 ")
			} else {
				prefix = TextChannelPrefix.Render("# ")
			}

			style := ChannelInactive
			if flatIdx == activeIdx {
				style = ChannelActive
			} else if flatIdx == hoverIdx {
				style = ChannelHover
			}

			label := ch.Name
			if len(label) > width-6 {
				label = label[:width-9] + "..."
			}
			lines = append(lines, style.Render(prefix+label))
			flatIdx++
		}
	}

	return ChannelListStyle.
		Width(width).
		Height(height).
		Render(strings.Join(lines, "\n"))
}

// ChannelFlatIndex converts a (category, channel index in category) to flat index.
func ChannelFlatIndex(channels []Channel, targetID string) int {
	catOrder := getCatOrder(channels)
	flatIdx := 0
	for _, catName := range catOrder {
		for _, ch := range groupByCategory(channels)[catName] {
			if ch.ID == targetID {
				return flatIdx
			}
			flatIdx++
		}
	}
	return 0
}

// ChannelByFlatIndex returns the channel at a flat index in the grouped view.
func ChannelByFlatIndex(channels []Channel, flatIdx int) *Channel {
	catOrder := getCatOrder(channels)
	idx := 0
	for _, catName := range catOrder {
		for _, ch := range groupByCategory(channels)[catName] {
			if idx == flatIdx {
				return &ch
			}
			idx++
		}
	}
	return nil
}

func groupByCategory(channels []Channel) map[string][]Channel {
	m := make(map[string][]Channel)
	for _, ch := range channels {
		cat := ch.Category
		if cat == "" {
			cat = "general"
		}
		m[cat] = append(m[cat], ch)
	}
	return m
}

func getCatOrder(channels []Channel) []string {
	seen := make(map[string]bool)
	var order []string
	for _, ch := range channels {
		cat := ch.Category
		if cat == "" {
			cat = "general"
		}
		if !seen[cat] {
			seen[cat] = true
			order = append(order, cat)
		}
	}
	sort.Strings(order)
	return order
}

// ChannelCount returns total number of channels (for navigation limits).
func ChannelCount(channels []Channel) int {
	return len(channels)
}

// formatChannelHeader renders the channel header for the chat pane.
func formatChannelHeader(ch Channel) string {
	icon := "#"
	if ch.Type == "voice" {
		icon = "🔊"
	}
	return fmt.Sprintf("%s %s", icon, ch.Name)
}
