package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"os"
	"strings"
	"testing"
	"time"
)

// TestSurecYardimci: test ikilisinin cocuk surec olarak calisan hali. Yalnizca ortam
// degiskeni ayarliysa calisir; stdin satirlarina cevap verir ve olay uretir.
func TestSurecYardimci(t *testing.T) {
	if os.Getenv("FIKOYT_SUREC_YARDIMCI") != "1" {
		return
	}
	okuyucu := bufio.NewScanner(os.Stdin)
	for okuyucu.Scan() {
		satir := okuyucu.Text()
		switch {
		case strings.Contains(satir, `"ping"`):
			fmt.Fprintln(os.Stdout, `{"tip":"cevap","tamam":true}`)
		case strings.Contains(satir, `"olay-iste"`):
			fmt.Fprintln(os.Stdout, `{"tip":"olay","veri":"merhaba"}`)
		case strings.Contains(satir, `"cik"`):
			os.Exit(0)
		}
	}
	os.Exit(0)
}

func surecSatiriBekle(t *testing.T, kanal <-chan string, icerik string) {
	t.Helper()
	select {
	case satir := <-kanal:
		if !strings.Contains(satir, icerik) {
			t.Fatalf("beklenen %q, gelen %q", icerik, satir)
		}
	case <-time.After(5 * time.Second):
		t.Fatalf("%q icin cevap gelmedi", icerik)
	}
}

func TestSurecBaslatGonderDurdur(t *testing.T) {
	t.Setenv("FIKOYT_SUREC_YARDIMCI", "1")
	satirlar := make(chan string, 10)
	y := yeniSurecYoneticisi(func(anahtar string, satir []byte) {
		var m map[string]any
		if json.Unmarshal(satir, &m) == nil {
			satirlar <- string(satir)
		}
	})

	if err := y.Baslat("test", os.Args[0], "-test.run=TestSurecYardimci"); err != nil {
		t.Fatal(err)
	}
	if !y.Calisiyor("test") {
		t.Fatal("süreç başladı ama çalışıyor görünmüyor")
	}
	if err := y.Baslat("test", os.Args[0]); err != errSurecCalisiyor {
		t.Fatalf("aynı anahtar ikinci kez başlatılmamalı: %v", err)
	}

	if err := y.Gonder("test", map[string]string{"islem": "ping"}); err != nil {
		t.Fatal(err)
	}
	surecSatiriBekle(t, satirlar, `"tamam":true`)

	if err := y.Gonder("test", map[string]string{"islem": "olay-iste"}); err != nil {
		t.Fatal(err)
	}
	surecSatiriBekle(t, satirlar, `"tip":"olay"`)

	if err := y.Durdur("test"); err != nil {
		t.Fatal(err)
	}
	if y.Calisiyor("test") {
		t.Fatal("durdurulan süreç hâlâ çalışıyor")
	}
	if err := y.Gonder("test", map[string]string{"islem": "ping"}); err != errSurecYok {
		t.Fatalf("durdurulmuş sürece mesaj gitmemeli: %v", err)
	}
}

func TestSurecBeklenmedikCikisKaydiSiler(t *testing.T) {
	t.Setenv("FIKOYT_SUREC_YARDIMCI", "1")
	y := yeniSurecYoneticisi(nil)
	if err := y.Baslat("test", os.Args[0], "-test.run=TestSurecYardimci"); err != nil {
		t.Fatal(err)
	}
	if err := y.Gonder("test", map[string]string{"islem": "cik"}); err != nil {
		t.Fatal(err)
	}
	// Surec kendiliginden cikinca kayit silinmeli.
	for i := 0; i < 50 && y.Calisiyor("test"); i++ {
		time.Sleep(100 * time.Millisecond)
	}
	if y.Calisiyor("test") {
		t.Fatal("çıkan süreç kayıtta kaldı")
	}
}
