package logging

import (
	"bytes"
	"encoding/json"
	"log/slog"
	"strings"
	"testing"
)

// Уровень — это адресат, а не громкость: DEBUG предназначен разработчику при
// отладке и в штатной работе наружу не выходит.
func TestУровеньОтсекаетНижние(t *testing.T) {
	t.Parallel()

	var buf bytes.Buffer
	log := NewTo(&buf, "warn", "json")
	log.Debug("отладка")
	log.Info("событие")
	log.Warn("может стать проблемой")

	out := buf.String()
	if strings.Contains(out, "отладка") || strings.Contains(out, "событие") {
		t.Errorf("уровень warn пропустил записи ниже себя: %s", out)
	}
	if !strings.Contains(out, "может стать проблемой") {
		t.Errorf("запись уровня warn потерялась: %s", out)
	}
}

// Время в логах — UTC: иначе порядок событий между машинами не сравнить.
func TestВремяВUTC(t *testing.T) {
	t.Parallel()

	var buf bytes.Buffer
	NewTo(&buf, "info", "json").Info("событие")

	var rec map[string]any
	if err := json.Unmarshal(buf.Bytes(), &rec); err != nil {
		t.Fatalf("запись не JSON: %v (%s)", err, buf.String())
	}
	ts, _ := rec[slog.TimeKey].(string)
	if !strings.HasSuffix(ts, "Z") {
		t.Errorf("метка времени %q не в UTC", ts)
	}
}

// Команды CLI пишут отчёт в stdout, поэтому их лог обязан идти в stderr —
// иначе отчёт не разобрать ни глазами, ни перенаправлением.
func TestNewErrПишетВStderrАNewВStdout(t *testing.T) {
	t.Parallel()

	// Прямой проверки потока здесь нет намеренно: подмена os.Stdout была бы
	// мутацией глобала. Проверяем то, что от этих конструкторов зависит на
	// самом деле, — что они собирают разные назначения и оба живые.
	if New("info", "json") == nil || NewErr("info", "text") == nil {
		t.Fatal("конструктор вернул nil")
	}

	var buf bytes.Buffer
	NewTo(&buf, "info", "text").Info("событие", "ключ", "значение")
	if !strings.Contains(buf.String(), "ключ=значение") {
		t.Errorf("текстовый формат не применён: %s", buf.String())
	}
}
