package logger

import (
	"fmt"

	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/config"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

// emojiCore wraps a zapcore.Core to add emoji icon field
type emojiCore struct {
	zapcore.Core
}

func (c *emojiCore) With(fields []zapcore.Field) zapcore.Core {
	return &emojiCore{c.Core.With(fields)}
}

func (c *emojiCore) Check(entry zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
	if c.Enabled(entry.Level) {
		return ce.AddCore(entry, c)
	}
	return ce
}

func (c *emojiCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
	// Only add emoji icon field for warnings and errors
	// Skip for info and debug to keep output clean
	var emoji string
	var addEmoji bool

	switch entry.Level {
	case zapcore.WarnLevel:
		emoji = "🟡" // Yellow circle for warnings
		addEmoji = true
	case zapcore.ErrorLevel:
		emoji = "🔴" // Red circle for errors
		addEmoji = true
	case zapcore.DPanicLevel:
		emoji = "🔴" // Red circle for panic
		addEmoji = true
	case zapcore.PanicLevel:
		emoji = "🔴" // Red circle for panic
		addEmoji = true
	case zapcore.FatalLevel:
		emoji = "🔴" // Red circle for fatal
		addEmoji = true
	default:
		// No emoji for debug and info levels
		addEmoji = false
	}

	// Only prepend emoji field if we're adding one
	if addEmoji {
		fieldsWithEmoji := make([]zapcore.Field, 0, len(fields)+1)
		fieldsWithEmoji = append(fieldsWithEmoji, zap.String("ico", emoji))
		fieldsWithEmoji = append(fieldsWithEmoji, fields...)
		return c.Core.Write(entry, fieldsWithEmoji)
	}

	// For debug/info, write as-is without emoji
	return c.Core.Write(entry, fields)
}

// ProvideLogger creates a new zap logger based on configuration
func ProvideLogger(cfg *config.Config) (*zap.Logger, error) {
	var zapConfig zap.Config

	// Set config based on environment
	if cfg.App.Environment == "production" {
		zapConfig = zap.NewProductionConfig()
	} else {
		zapConfig = zap.NewDevelopmentConfig()
	}

	// Set log level
	level, err := zapcore.ParseLevel(cfg.Logger.Level)
	if err != nil {
		return nil, fmt.Errorf("invalid log level %s: %w", cfg.Logger.Level, err)
	}
	zapConfig.Level = zap.NewAtomicLevelAt(level)

	// Set encoding format
	if cfg.Logger.Format == "console" {
		zapConfig.Encoding = "console"
		zapConfig.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
	} else {
		zapConfig.Encoding = "json"
	}

	// Build logger with environment-specific options
	var loggerOptions []zap.Option

	// Enable caller information in development for easier debugging
	if cfg.App.Environment != "production" {
		loggerOptions = append(loggerOptions, zap.AddCaller())
		loggerOptions = append(loggerOptions, zap.AddCallerSkip(0))
	}

	// Add stack traces for error level and above
	loggerOptions = append(loggerOptions, zap.AddStacktrace(zapcore.ErrorLevel))

	// Wrap core with emoji core to add icon field
	loggerOptions = append(loggerOptions, zap.WrapCore(func(core zapcore.Core) zapcore.Core {
		return &emojiCore{core}
	}))

	logger, err := zapConfig.Build(loggerOptions...)
	if err != nil {
		return nil, fmt.Errorf("failed to build logger: %w", err)
	}

	logger.Info("✓ Logger initialized",
		zap.String("level", cfg.Logger.Level),
		zap.String("format", cfg.Logger.Format),
		zap.String("environment", cfg.App.Environment))

	return logger, nil
}
