package collaboration

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"path"
	"strings"
	"time"
)

func NormalizeFolderPath(raw string) (string, error) {
	raw = strings.TrimSpace(strings.ReplaceAll(raw, "\\", "/"))
	if raw == "" || raw == "/" {
		return "", nil
	}
	clean := path.Clean(strings.Trim(raw, "/"))
	if clean == "." {
		return "", nil
	}
	if clean == ".." || strings.HasPrefix(clean, "../") {
		return "", fmt.Errorf("folder path must remain inside the content root")
	}
	return clean, nil
}

func randomID(prefix string) string {
	buf := make([]byte, 12)
	if _, err := rand.Read(buf); err != nil {
		panic(err)
	}
	return prefix + ":" + hex.EncodeToString(buf)
}

func hashAnchor(text string) string {
	normalized := strings.TrimSpace(text)
	sum := sha256.Sum256([]byte(normalized))
	return hex.EncodeToString(sum[:8])
}

func parseTime(raw string) (time.Time, error) {
	if raw == "" {
		return time.Time{}, nil
	}
	return time.Parse(time.RFC3339, raw)
}

func formatTime(t time.Time) string {
	return t.UTC().Format(time.RFC3339)
}

func ptr[T any](v T) *T {
	return &v
}

func nullString(s string) *string {
	if s == "" {
		return nil
	}
	return &s
}

func scanNullString(ns *string) string {
	if ns == nil {
		return ""
	}
	return *ns
}

func coalesceString(values ...string) string {
	for _, v := range values {
		if v != "" {
			return v
		}
	}
	return ""
}

func formatDocumentID(path string) string {
	clean := strings.TrimPrefix(path, "/")
	clean = strings.TrimSuffix(clean, ".md")
	return "doc:" + clean
}

func documentPathFromID(id string) string {
	return strings.TrimPrefix(id, "doc:")
}
