package cat

import (
	"log"
	"os"
	"path/filepath"
)

// LogSink, when set by the host app at startup, receives every CAT debug
// line so they land in the unified app log (opslog.log) alongside the rest
// of OpsLog's diagnostics. Until it's wired we fall back to a dedicated
// cat.log file so early-startup lines aren't lost.
var LogSink func(format string, args ...any)

// catLogger forwards Printf either to the host LogSink (preferred) or to a
// local file/stderr fallback. Keeps the call sites (debugLog.Printf(...))
// unchanged.
type catLogger struct{ fallback *log.Logger }

func (c *catLogger) Printf(format string, args ...any) {
	if LogSink != nil {
		LogSink("cat: "+format, args...)
		return
	}
	if c.fallback != nil {
		c.fallback.Printf(format, args...)
	}
}

// debugLog writes CAT debug events so users can diagnose mode/freq mismatches
// without rebuilding with a console. Once LogSink is set, lines flow into the
// main opslog.log.
var debugLog = &catLogger{fallback: openFallbackLog()}

func openFallbackLog() *log.Logger {
	base, err := os.UserConfigDir()
	if err != nil {
		return log.Default()
	}
	dir := filepath.Join(base, "OpsLog")
	if err := os.MkdirAll(dir, 0o755); err != nil {
		return log.Default()
	}
	f, err := os.OpenFile(filepath.Join(dir, "cat.log"),
		os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
	if err != nil {
		return log.Default()
	}
	return log.New(f, "", log.LstdFlags|log.Lmicroseconds)
}

// DebugLogPath returns where the fallback cat.log lives, for surfacing in the
// UI / docs. When LogSink is wired, CAT lines are in the main app log instead.
func DebugLogPath() string {
	base, err := os.UserConfigDir()
	if err != nil {
		return ""
	}
	return filepath.Join(base, "OpsLog", "cat.log")
}
