package logger

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sync"
	"time"
)

var (
	instance *Logger
	once     sync.Once
)

// Logger handles application logging
type Logger struct {
	file *os.File
	mu   sync.Mutex
	path string
}

// Init initializes the logger with timestamp-based filename
func Init() error {
	var err error
	once.Do(func() {
		// Create logs directory
		logsDir := "logs"
		if mkErr := os.MkdirAll(logsDir, 0755); mkErr != nil {
			err = mkErr
			return
		}

		// Create log file with timestamp
		timestamp := time.Now().Format("2006-01-02_15-04-05")
		filename := filepath.Join(logsDir, fmt.Sprintf("%s.log", timestamp))

		f, openErr := os.Create(filename)
		if openErr != nil {
			err = openErr
			return
		}

		instance = &Logger{
			file: f,
			path: filename,
		}

		Info("Logger initialized: %s", filename)
	})
	return err
}

// Close closes the logger
func Close() {
	if instance != nil && instance.file != nil {
		instance.file.Close()
	}
}

// GetPath returns the log file path
func GetPath() string {
	if instance != nil {
		return instance.path
	}
	return ""
}

// log writes a log entry
func log(level, format string, args ...interface{}) {
	if instance == nil {
		return
	}

	instance.mu.Lock()
	defer instance.mu.Unlock()

	timestamp := time.Now().Format("15:04:05.000")
	msg := fmt.Sprintf(format, args...)
	line := fmt.Sprintf("[%s] [%s] %s\n", timestamp, level, msg)

	instance.file.WriteString(line)
	instance.file.Sync()
}

// Debug logs a debug message
func Debug(format string, args ...interface{}) {
	log("DEBUG", format, args...)
}

// Info logs an info message
func Info(format string, args ...interface{}) {
	log("INFO", format, args...)
}

// Warn logs a warning message
func Warn(format string, args ...interface{}) {
	log("WARN", format, args...)
}

// Error logs an error message
func Error(format string, args ...interface{}) {
	log("ERROR", format, args...)
}

// Writer returns an io.Writer that logs to the file
func Writer() io.Writer {
	if instance != nil {
		return instance.file
	}
	return os.Stdout
}
