package main

import (
	"context"
	"os"
	"testing"
	"time"
)

// TestEkCocukSurecKapanisi: guncelleme cikisindan once eklentileriKapat calisan surec ve oturumlari kapatmali.
func TestEkCocukSurecKapanisi(t *testing.T) {
	t.Setenv("FIKOYT_EK_YARDIMCI", "1")
	t.Setenv("FIKOYT_EK_MOD", "normal")
	ekTemizle(t)

	const anahtar = "test-kapanis"
	o, err := ekOturumAl(anahtar, os.Args[0], ekYardimciArgs())
	if err != nil {
		t.Fatalf("oturum acilamadi: %v", err)
	}
	eklentileriKapat()

	select {
	case <-o.kapali:
	case <-time.After(10 * time.Second):
		t.Fatal("eklentileriKapat sonrasi surec kapanmadi")
	}
	ekMu.Lock()
	_, hala := ekOturumlar[anahtar]
	ekMu.Unlock()
	if hala {
		t.Fatal("kapanan oturum listede kaldi")
	}
}

// TestEkKapanisTakilanEklentiyiBekletmez: yanit vermeyen (uyuyan) eklenti kapanisi ekKapatZamanAsimi'ndan
// fazla geciktirmemeli. Surec izle() ile oldurulur; bekleme ust siniri asilmamali.
func TestEkKapanisTakilanEklentiyiBekletmez(t *testing.T) {
	t.Setenv("FIKOYT_EK_YARDIMCI", "1")
	t.Setenv("FIKOYT_EK_MOD", "normal")
	ekTemizle(t)

	o, err := ekOturumAl("test-kapanis-takili", os.Args[0], ekYardimciArgs())
	if err != nil {
		t.Fatalf("oturum acilamadi: %v", err)
	}
	go func() {
		ctx, iptal := context.WithTimeout(context.Background(), 10*time.Second)
		defer iptal()
		_, _ = ekCagir(ctx, "test-kapanis-takili", os.Args[0], ekYardimciArgs(), "uyu", nil, nil)
	}()
	time.Sleep(200 * time.Millisecond)

	basla := time.Now()
	eklentileriKapat()
	gecen := time.Since(basla)
	if gecen > ekKapatZamanAsimi+time.Second {
		t.Fatalf("kapanis %v surdu, ust sinir %v", gecen, ekKapatZamanAsimi)
	}
	select {
	case <-o.kapali:
	case <-time.After(10 * time.Second):
		t.Fatal("takili eklenti sureci kapanmadi")
	}
}

// TestEkCagriZamanAsimi: baglam suresi dolunca cagri yanit beklemeden doner.
func TestEkCagriZamanAsimi(t *testing.T) {
	t.Setenv("FIKOYT_EK_YARDIMCI", "1")
	t.Setenv("FIKOYT_EK_MOD", "normal")
	ekTemizle(t)

	ctx, iptal := context.WithTimeout(context.Background(), 200*time.Millisecond)
	defer iptal()
	basla := time.Now()
	_, err := ekCagir(ctx, "test-zaman-asimi", os.Args[0], ekYardimciArgs(), "uyu", nil, nil)
	gecen := time.Since(basla)
	if err == nil {
		t.Fatal("zaman asimina ugrayan cagri hata dondurmeliydi")
	}
	if gecen > 2*time.Second {
		t.Fatalf("zaman asimi 200 ms'de donmeliydi, gecen: %v", gecen)
	}
}

// TestEkYavasEklentiDigerleriEtkilemez: bir eklenti yanit vermezken, ayni anda calisan diger eklentinin
// cagrisi kendi zaman sinirinda tamamlanmali.
func TestEkYavasEklentiDigerleriEtkilemez(t *testing.T) {
	t.Setenv("FIKOYT_EK_YARDIMCI", "1")
	t.Setenv("FIKOYT_EK_MOD", "normal")
	ekTemizle(t)

	go func() {
		ctx, iptal := context.WithTimeout(context.Background(), 10*time.Second)
		defer iptal()
		_, _ = ekCagir(ctx, "test-yavas", os.Args[0], ekYardimciArgs(), "uyu", nil, nil)
	}()
	time.Sleep(200 * time.Millisecond)

	ctx, iptal := context.WithTimeout(context.Background(), time.Second)
	defer iptal()
	basla := time.Now()
	sonuc, err := ekCagir(ctx, "test-hizli", os.Args[0], ekYardimciArgs(), "ara", nil, nil)
	gecen := time.Since(basla)
	if err != nil {
		t.Fatalf("hizli eklenti yavas eklentiden etkilendi: %v", err)
	}
	if gecen > time.Second {
		t.Fatalf("hizli cagri 1 sn icinde donmeliydi, gecen: %v", gecen)
	}
	if string(sonuc) != `{"parcaId":"p1"}` {
		t.Fatalf("beklenmeyen sonuc: %s", sonuc)
	}
}
