package main

import (
	"context"
	"errors"
	"io"
	"log/slog"
	"reflect"
	"testing"
)

// fakeCloser kapanış sırasını kaydeder (ve istenirse hata döndürür).
type fakeCloser struct {
	name  string
	order *[]string
	err   error
}

func (f *fakeCloser) Close(context.Context) error {
	*f.order = append(*f.order, f.name)
	return f.err
}

func TestShutdownOrder(t *testing.T) {
	var order []string
	log := slog.New(slog.NewTextHandler(io.Discard, nil))

	ag := &fakeCloser{name: "agent", order: &order}
	hub := &fakeCloser{name: "hub", order: &order}
	srv := &fakeCloser{name: "http", order: &order}

	shutdownWith(context.Background(), log, ag, hub, srv)

	want := []string{"agent", "hub", "http"}
	if !reflect.DeepEqual(order, want) {
		t.Fatalf("kapanış sırası = %v, beklenen %v (agent → hub → http)", order, want)
	}
}

// Bir bileşenin hata vermesi kapanış zincirini durdurmamalı: kalan bileşenler kapanır,
// hata yalnızca loglanır (aksi hâlde HTTP dinleyicisi açık kalır).
func TestShutdownContinuesAfterError(t *testing.T) {
	var order []string
	log := slog.New(slog.NewTextHandler(io.Discard, nil))
	boom := errors.New("patladı")

	ag := &fakeCloser{name: "agent", order: &order, err: boom}
	hub := &fakeCloser{name: "hub", order: &order, err: boom}
	srv := &fakeCloser{name: "http", order: &order, err: boom}

	shutdownWith(context.Background(), log, ag, hub, srv)

	if len(order) != 3 {
		t.Fatalf("hata durumunda zincir kırıldı, kapananlar = %v", order)
	}
	if order[len(order)-1] != "http" {
		t.Errorf("http en son kapanmalı, kapanışlar = %v", order)
	}
}
