package logging

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"time"
)

type Logger struct {
	level  string
	fields map[string]interface{}
}

func NewLogger(level string) *Logger {
	return &Logger{level: level, fields: make(map[string]interface{})}
}

func (l *Logger) WithField(key string, value interface{}) *Logger {
	out := &Logger{level: l.level, fields: make(map[string]interface{})}
	for k, v := range l.fields {
		out.fields[k] = v
	}
	out.fields[key] = value
	return out
}

func (l *Logger) Info(ctx context.Context, message string)  { l.log(ctx, "info", message, nil) }
func (l *Logger) Error(ctx context.Context, message string, err error) {
	l.log(ctx, "error", message, map[string]interface{}{"error": err.Error()})
}
func (l *Logger) Warn(ctx context.Context, message string)  { l.log(ctx, "warn", message, nil) }
func (l *Logger) Debug(ctx context.Context, message string) { l.log(ctx, "debug", message, nil) }

func (l *Logger) log(ctx context.Context, level, message string, extra map[string]interface{}) {
	entry := map[string]interface{}{
		"timestamp": time.Now().UTC().Format(time.RFC3339),
		"level":     level,
		"message":   message,
	}
	for k, v := range l.fields {
		entry[k] = v
	}
	if extra != nil {
		for k, v := range extra {
			entry[k] = v
		}
	}
	entry = sanitizePII(entry)
	jsonBytes, err := json.Marshal(entry)
	if err != nil {
		log.Printf("marshal log: %v", err)
		return
	}
	fmt.Fprintln(os.Stdout, string(jsonBytes))
}

func sanitizePII(entry map[string]interface{}) map[string]interface{} {
	out := make(map[string]interface{})
	for k, v := range entry {
		if k == "password" || k == "api_key" || k == "token" {
			out[k] = "***REDACTED***"
		} else {
			out[k] = v
		}
	}
	return out
}
