package channel

import (
	"crypto/sha256"
	"encoding/hex"
	"strings"
	"unicode"
)

const channelSlugMaxLength = 63

func deriveChannelSlug(displayName string, channelID string) string {
	slug, lossy := slugifyChannelDisplayNameWithLossy(displayName)
	if lossy || slug == "" || slug == "all" || strings.HasPrefix(slug, "thread-") {
		slug = fallbackChannelSlug(channelID)
	}
	return slug
}

func slugifyChannelDisplayName(displayName string) string {
	slug, _ := slugifyChannelDisplayNameWithLossy(displayName)
	return slug
}

func slugifyChannelDisplayNameWithLossy(displayName string) (string, bool) {
	slug := strings.ToLower(strings.TrimSpace(displayName))
	lossy := false
	slug = strings.Map(func(r rune) rune {
		switch {
		case r >= 'a' && r <= 'z':
			return r
		case r >= '0' && r <= '9':
			return r
		case r == '-' || unicode.IsSpace(r):
			return '-'
		default:
			lossy = true
			return '-'
		}
	}, slug)
	slug = strings.Trim(slug, "-")
	for strings.Contains(slug, "--") {
		slug = strings.ReplaceAll(slug, "--", "-")
	}
	if len(slug) > channelSlugMaxLength {
		lossy = true
		slug = strings.TrimRight(slug[:channelSlugMaxLength], "-")
	}
	return slug, lossy
}

func fallbackChannelSlug(channelID string) string {
	suffix := strings.ToLower(strings.TrimSpace(channelID))
	if _, after, ok := strings.Cut(suffix, "_"); ok {
		suffix = after
	}
	suffix = slugifyChannelDisplayName(suffix)
	if len(suffix) > 8 {
		suffix = suffix[:8]
	}
	suffix = strings.Trim(suffix, "-")
	if suffix == "" {
		return "channel"
	}
	return "channel-" + suffix
}

func ArchivedScopeProfileSlug(scopeID string) string {
	normalized := strings.ToLower(strings.TrimSpace(scopeID))
	stem := strings.Map(func(r rune) rune {
		switch {
		case r >= 'a' && r <= 'z':
			return r
		case r >= '0' && r <= '9':
			return r
		default:
			return '-'
		}
	}, normalized)
	stem = strings.Trim(stem, "-")
	for strings.Contains(stem, "--") {
		stem = strings.ReplaceAll(stem, "--", "-")
	}
	if stem == "" {
		stem = "scope"
	}

	sum := sha256.Sum256([]byte(scopeID))
	hash := hex.EncodeToString(sum[:])[:12]
	const prefix = "deleted-"
	maxStemLength := 63 - len(prefix) - len("-") - len(hash)
	if maxStemLength < 1 {
		maxStemLength = 1
	}
	if len(stem) > maxStemLength {
		stem = strings.Trim(stem[:maxStemLength], "-")
	}
	if stem == "" {
		stem = "scope"
	}
	return prefix + stem + "-" + hash
}
