// backend/internal/naming.go
package internal

import (
	"fmt"
	"path/filepath"
	"regexp"
	"strings"
	"time"
)

var (
	descMax           = 64
	allowedDesc       = regexp.MustCompile(`[^A-Za-z0-9 _-]`)     // to be replaced by `_`
	dateOnly          = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}$`) // UI sends YYYY-MM-DD
	finalNameValidate = regexp.MustCompile(`^\d{4}\.\d{2}\.\d{2}\.[A-Za-z0-9_-]{1,64}\.[A-Za-z0-9]{1,8}$`)
)

// SanitizeDesc normalizes a free-form description into a safe filename segment.
func SanitizeDesc(in string) string {
	s := strings.TrimSpace(in)
	if s == "" {
		s = "upload"
	}
	s = allowedDesc.ReplaceAllString(s, "_")
	s = strings.Join(strings.Fields(s), "_") // collapse whitespace
	if len(s) > descMax {
		s = s[:descMax]
	}
	return s
}

// ComposeFinalName builds the on-disk upload filename from the user date, description, and original name.
func ComposeFinalName(dateStr, desc, origFilename string) (string, error) {
	ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(origFilename), "."))
	if ext == "" {
		ext = "bin"
	}

	var t time.Time
	var err error
	if dateOnly.MatchString(dateStr) {
		t, err = time.Parse("2006-01-02", dateStr)
	} else {
		t = time.Now()
	}
	if err != nil {
		return "", fmt.Errorf("bad date")
	}

	final := fmt.Sprintf("%04d.%02d.%02d.%s.%s", t.Year(), int(t.Month()), t.Day(), SanitizeDesc(desc), ext)
	if !finalNameValidate.MatchString(final) {
		return "", fmt.Errorf("invalid final name")
	}
	return final, nil
}
