package main

import (
	"encoding/json"
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"
)

// Gercek imzali paketle uctan uca zincir. Yalnizca FIKOYT_E2E_KLASOR ayarliysa calisir.
// Klasor: plugin.exe ve manifest.json icermeli. Kurulum GECICI APPDATA'da yapilir; gercek kayitlara dokunulmaz.
// Eklenti surekli calisan surec olarak sinanir: ping -> cevap, sonra durdur, devre disi ve kaldir.
func TestE2EKurulumZinciri(t *testing.T) {
	klasor := os.Getenv("FIKOYT_E2E_KLASOR")
	if klasor == "" {
		t.Skip("FIKOYT_E2E_KLASOR ayarli degil")
	}
	t.Setenv("APPDATA", t.TempDir())
	// Yalnizca test icin: ayri bir test anahtariyla imzalanmis paket. Uretim anahtari degismez.
	if acik := os.Getenv("FIKOYT_E2E_ACIK_ANAHTAR"); acik != "" {
		paketAcikAnahtar = acik
	}

	var p paketBilgisi
	veri, err := os.ReadFile(filepath.Join(klasor, "manifest.json"))
	if err != nil {
		t.Fatal(err)
	}
	if err := json.Unmarshal(veri, &p); err != nil {
		t.Fatal(err)
	}
	dosya, err := os.ReadFile(filepath.Join(klasor, "plugin.exe"))
	if err != nil {
		t.Fatal(err)
	}

	if err := eklentiKur(p, dosya); err != nil {
		t.Fatalf("kurulum basarisiz: %v", err)
	}
	if !kuruluEtkinMi(p.Anahtar) {
		t.Fatal("kurulumdan sonra etkin degil")
	}
	yol, err := kuruluEklentiYolu(p.Anahtar)
	if err != nil {
		t.Fatalf("yol bulunamadi: %v", err)
	}

	// Surec olarak baslat, ping gonder, cevap bekle.
	cevaplar := make(chan string, 10)
	y := yeniSurecYoneticisi(func(anahtar string, satir []byte) {
		if strings.Contains(string(satir), `"tip":"cevap"`) {
			cevaplar <- string(satir)
		}
	})
	if err := y.Baslat(p.Anahtar, yol); err != nil {
		t.Fatalf("surec baslatilamadi: %v", err)
	}
	if err := y.Gonder(p.Anahtar, map[string]string{"islem": "ping"}); err != nil {
		t.Fatalf("ping gonderilemedi: %v", err)
	}
	select {
	case satir := <-cevaplar:
		if !strings.Contains(satir, `"tamam":true`) {
			t.Fatalf("ping cevabi basarisiz: %s", satir)
		}
	case <-time.After(10 * time.Second):
		t.Fatal("ping icin cevap gelmedi")
	}
	if err := y.Durdur(p.Anahtar); err != nil {
		t.Fatalf("surec durdurulamadi: %v", err)
	}

	if err := kuruluEtkinAyarla(p.Anahtar, false); err != nil {
		t.Fatal(err)
	}
	if kuruluEtkinMi(p.Anahtar) {
		t.Fatal("devre disi birakildi ama hala etkin")
	}
	if err := eklentiKaldir(p.Anahtar); err != nil {
		t.Fatal(err)
	}
	if kuruluVarMi(p.Anahtar) {
		t.Fatal("kaldirildi ama kayit duruyor")
	}
}

// Tek seferlik eklentiler (ornek: everything): her cagri ayri surec, stdin'den bir satir okur, bir satir yazar.
// Surekli surec (ping/olay) beklenmez. Calistirmak icin: FIKOYT_E2E_KLASOR ve FIKOYT_E2E_MOD=tekseferlik.
func TestE2ETekSeferlikZincir(t *testing.T) {
	klasor := os.Getenv("FIKOYT_E2E_KLASOR")
	if klasor == "" || os.Getenv("FIKOYT_E2E_MOD") != "tekseferlik" {
		t.Skip("FIKOYT_E2E_KLASOR ve FIKOYT_E2E_MOD=tekseferlik ayarli degil")
	}
	t.Setenv("APPDATA", t.TempDir())
	if acik := os.Getenv("FIKOYT_E2E_ACIK_ANAHTAR"); acik != "" {
		paketAcikAnahtar = acik
	}

	var p paketBilgisi
	veri, err := os.ReadFile(filepath.Join(klasor, "manifest.json"))
	if err != nil {
		t.Fatal(err)
	}
	if err := json.Unmarshal(veri, &p); err != nil {
		t.Fatal(err)
	}
	dosya, err := os.ReadFile(filepath.Join(klasor, "plugin.exe"))
	if err != nil {
		t.Fatal(err)
	}

	if err := eklentiKur(p, dosya); err != nil {
		t.Fatalf("kurulum basarisiz: %v", err)
	}
	if !kuruluEtkinMi(p.Anahtar) {
		t.Fatal("kurulumdan sonra etkin degil")
	}
	yol, err := kuruluEklentiYolu(p.Anahtar)
	if err != nil {
		t.Fatalf("yol bulunamadi: %v", err)
	}

	// Tek seferlik ping: cevap tamam olmali.
	cikti, err := eklentiCalistir(yol, nil, eklentiGirdi{Islem: "ping"}, calistirZamanAsimi)
	if err != nil {
		t.Fatalf("ping calismadi: %v", err)
	}
	if !cikti.Tamam {
		t.Fatalf("ping cevabi basarisiz: %+v", cikti)
	}

	// Gecersiz port ayari reddedilmeli (ag cagrisi yapilmadan).
	gecersiz, err := eklentiCalistir(yol, nil, eklentiGirdi{
		Islem: "ara",
		Veri:  json.RawMessage(`{"sorgu":"test"}`),
		Ayar:  json.RawMessage(`{"port":70000}`),
	}, calistirZamanAsimi)
	if err != nil {
		t.Fatalf("gecersiz port cagrisi calismadi: %v", err)
	}
	if gecersiz.Tamam {
		t.Fatal("gecersiz port kabul edildi")
	}

	if err := kuruluEtkinAyarla(p.Anahtar, false); err != nil {
		t.Fatal(err)
	}
	if err := eklentiKaldir(p.Anahtar); err != nil {
		t.Fatal(err)
	}
	if kuruluVarMi(p.Anahtar) {
		t.Fatal("kaldirildi ama kayit duruyor")
	}
}
