package main

import (
	"crypto/ed25519"
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"testing"
)

// Testler anahtari calisma aninda uretir; hicbir gizli anahtar diske yazilmaz.
func testPaket(t *testing.T, dosya []byte) (paketBilgisi, string) {
	t.Helper()
	pub, priv, err := ed25519.GenerateKey(rand.Reader)
	if err != nil {
		t.Fatal(err)
	}
	ozet := sha256.Sum256(dosya)
	p := paketBilgisi{Anahtar: "ornek", Surum: "1.0.0", Sha256: hex.EncodeToString(ozet[:])}
	p.Imza = base64.StdEncoding.EncodeToString(ed25519.Sign(priv, imzaliMetin(p)))
	return p, base64.StdEncoding.EncodeToString(pub)
}

func TestPaketGecerli(t *testing.T) {
	dosya := []byte("ikili icerik")
	p, anahtar := testPaket(t, dosya)
	if err := paketDogrula(p, anahtar, dosya); err != nil {
		t.Fatalf("gecerli paket reddedildi: %v", err)
	}
}

func TestPaketDosyaDegisirse(t *testing.T) {
	dosya := []byte("ikili icerik")
	p, anahtar := testPaket(t, dosya)
	if err := paketDogrula(p, anahtar, []byte("degistirilmis")); err != errPaketOzet {
		t.Fatalf("beklenen ozet hatasi, gelen: %v", err)
	}
}

func TestPaketManifestDegisirse(t *testing.T) {
	dosya := []byte("ikili icerik")
	p, anahtar := testPaket(t, dosya)
	p.Surum = "9.9.9" // imzali alan degisti
	if err := paketDogrula(p, anahtar, dosya); err != errPaketImza {
		t.Fatalf("beklenen imza hatasi, gelen: %v", err)
	}
}

func TestPaketYanlisAnahtar(t *testing.T) {
	dosya := []byte("ikili icerik")
	p, _ := testPaket(t, dosya)
	_, baskaAnahtar := testPaket(t, dosya)
	if err := paketDogrula(p, baskaAnahtar, dosya); err != errPaketImza {
		t.Fatalf("beklenen imza hatasi, gelen: %v", err)
	}
}

func TestPaketAnahtarTanimsizKurulumKapali(t *testing.T) {
	dosya := []byte("ikili icerik")
	p, anahtar := testPaket(t, dosya)
	if err := paketDogrula(p, "", dosya); err != errPaketAnahtarYok {
		t.Fatalf("bos anahtar kabul edildi: %v", err)
	}
	_ = anahtar
}

// v2 paket: acilis bayragi imzaya dahil; dogru imzali paket kabul edilir ve bayrak okunur.
func TestPaketV2AcilisImzali(t *testing.T) {
	dosya := []byte("ikili icerik")
	pub, priv, err := ed25519.GenerateKey(rand.Reader)
	if err != nil {
		t.Fatal(err)
	}
	ozet := sha256.Sum256(dosya)
	p := paketBilgisi{Anahtar: "ornek", Surum: "1.0.2", Sha256: hex.EncodeToString(ozet[:]), Bicim: "v2", Acilis: true}
	p.Imza = base64.StdEncoding.EncodeToString(ed25519.Sign(priv, imzaliMetin(p)))
	anahtar := base64.StdEncoding.EncodeToString(pub)
	if err := paketDogrula(p, anahtar, dosya); err != nil {
		t.Fatalf("gecerli v2 paket reddedildi: %v", err)
	}
	if !acilisiIstiyor(p) {
		t.Fatal("imzali acilis bayragi okunmadi")
	}
}

// Imzali v2 pakette acilis bayragi sonradan 1 -> 0 yapilirsa imza bozulmali.
func TestPaketV2AcilisDegistirilirse(t *testing.T) {
	dosya := []byte("ikili icerik")
	pub, priv, err := ed25519.GenerateKey(rand.Reader)
	if err != nil {
		t.Fatal(err)
	}
	ozet := sha256.Sum256(dosya)
	p := paketBilgisi{Anahtar: "ornek", Surum: "1.0.2", Sha256: hex.EncodeToString(ozet[:]), Bicim: "v2", Acilis: false}
	p.Imza = base64.StdEncoding.EncodeToString(ed25519.Sign(priv, imzaliMetin(p)))
	p.Acilis = true // saldiri: bayragi acmak
	if err := paketDogrula(p, base64.StdEncoding.EncodeToString(pub), dosya); err != errPaketImza {
		t.Fatalf("beklenen imza hatasi, gelen: %v", err)
	}
}

// v1 paket (eski, acilis imzalanmaz): acilis=true yazilsa bile acilisiIstiyor false donmeli.
func TestPaketV1AcilisYokSayilir(t *testing.T) {
	dosya := []byte("ikili icerik")
	p, anahtar := testPaket(t, dosya)
	p.Acilis = true
	if err := paketDogrula(p, anahtar, dosya); err != nil {
		t.Fatalf("v1 paket reddedildi: %v", err)
	}
	if acilisiIstiyor(p) {
		t.Fatal("v1 pakette acilis bayragi kabul edildi (guvenlik acigi)")
	}
}
