package stdout

import (
	"bytes"
	"context"
	"os"
	"testing"
	"time"

	"github.com/antitbone/ja4/correlator/internal/domain"
)

func makeLog(correlated int) domain.CorrelatedLog {
	return domain.CorrelatedLog{
		Timestamp:  time.Unix(1700000000, 0),
		SrcIP:      "1.2.3.4",
		SrcPort:    12345,
		Correlated: correlated,
	}
}

// captureStdout replaces os.Stdout temporarily and returns what was written.
func captureStdout(t *testing.T, fn func()) string {
	t.Helper()
	r, w, err := os.Pipe()
	if err != nil {
		t.Fatalf("os.Pipe: %v", err)
	}
	old := os.Stdout
	os.Stdout = w

	fn()

	w.Close()
	os.Stdout = old

	var buf bytes.Buffer
	buf.ReadFrom(r)
	r.Close()
	return buf.String()
}

func TestStdoutSink_Name(t *testing.T) {
	s := NewStdoutSink(Config{Enabled: true})
	if s.Name() != "stdout" {
		t.Errorf("expected name 'stdout', got %q", s.Name())
	}
}

// TestStdoutSink_WriteDoesNotProduceOutput verifies that no JSON data
// (correlated or not) is ever written to stdout.
func TestStdoutSink_WriteDoesNotProduceOutput(t *testing.T) {
	s := NewStdoutSink(Config{Enabled: true})

	got := captureStdout(t, func() {
		if err := s.Write(context.Background(), makeLog(1)); err != nil {
			t.Fatalf("Write(correlated) returned error: %v", err)
		}
		if err := s.Write(context.Background(), makeLog(0)); err != nil {
			t.Fatalf("Write(orphan) returned error: %v", err)
		}
	})

	if got != "" {
		t.Errorf("stdout must be empty but got: %q", got)
	}
}

func TestStdoutSink_NoopMethods(t *testing.T) {
	s := NewStdoutSink(Config{Enabled: true})

	if err := s.Flush(context.Background()); err != nil {
		t.Errorf("Flush returned error: %v", err)
	}
	if err := s.Close(); err != nil {
		t.Errorf("Close returned error: %v", err)
	}
	if err := s.Reopen(); err != nil {
		t.Errorf("Reopen returned error: %v", err)
	}
}
