// fikoyt-eklenti-imzala: bridge deposunun DISINDA calisir. Ozel anahtar bu koda ve bu depoya girmez.
//
//	-uret <dosya>                      yeni Ed25519 anahtari uretir (seed base64), acik anahtari yazar
//	-key <dosya> -eklenti -surum -dosya -cikti   manifest.json uretir ve imzalar
package main

import (
	"crypto/ed25519"
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"strings"
)

type manifest struct {
	Anahtar string `json:"anahtar"`
	Surum   string `json:"surum"`
	Sha256  string `json:"sha256"`
	Imza    string `json:"imza"`
	Bicim   string `json:"bicim"`
	Acilis  bool   `json:"acilis"`
}

func kontrol(err error) {
	if err != nil {
		fmt.Fprintln(os.Stderr, "hata:", err)
		os.Exit(1)
	}
}

func main() {
	uret := flag.String("uret", "", "yeni anahtar dosyasi yolu")
	anahtarDosya := flag.String("key", "", "ozel anahtar dosyasi (base64 seed)")
	eklenti := flag.String("eklenti", "", "eklenti anahtari, ornek: ornek")
	surum := flag.String("surum", "1.0.0", "surum")
	dosya := flag.String("dosya", "", "plugin.exe yolu")
	cikti := flag.String("cikti", "", "manifest.json yolu")
	aciklama := flag.String("aciklama", "", "aciklama.json yolu: magaza aciklamasini imzalar (cikti: aciklama.imza.json)")
	acilis := flag.Bool("acilis", false, "acilista otomatik baslasin (v2 imza; kullanici kurulumda ayrica onaylar)")
	flag.Parse()

	if *uret != "" {
		pub, priv, err := ed25519.GenerateKey(rand.Reader)
		kontrol(err)
		kontrol(os.WriteFile(*uret, []byte(base64.StdEncoding.EncodeToString(priv.Seed())), 0600))
		fmt.Println(base64.StdEncoding.EncodeToString(pub))
		return
	}

	seedB64, err := os.ReadFile(*anahtarDosya)
	kontrol(err)
	seed, err := base64.StdEncoding.DecodeString(strings.TrimSpace(string(seedB64)))
	kontrol(err)
	// 32 bayt: seed. 64 bayt: keygen'in yazdigi tam ozel anahtar (seed || acik).
	var priv ed25519.PrivateKey
	switch len(seed) {
	case ed25519.SeedSize:
		priv = ed25519.NewKeyFromSeed(seed)
	case ed25519.PrivateKeySize:
		priv = ed25519.PrivateKey(seed)
	default:
		kontrol(fmt.Errorf("anahtar uzunlugu gecersiz: %d", len(seed)))
	}

	if *aciklama != "" {
		ham, err := os.ReadFile(*aciklama)
		kontrol(err)
		aOzet := sha256.Sum256(ham)
		aOzetHex := hex.EncodeToString(aOzet[:])
		// Web (aciklama-dogrula.ts) ile birebir ayni format.
		imzaMetni := []byte("fikoyt-aciklama-v1\n" + *eklenti + "\n" + aOzetHex)
		out, err := json.MarshalIndent(map[string]string{"ozet": aOzetHex, "imza": base64.StdEncoding.EncodeToString(ed25519.Sign(priv, imzaMetni))}, "", "  ")
		kontrol(err)
		kontrol(os.WriteFile(*cikti, out, 0644))
		fmt.Println("aciklama imzasi yazildi:", *cikti)
		return
	}

	veri, err := os.ReadFile(*dosya)
	kontrol(err)
	ozet := sha256.Sum256(veri)
	ozetHex := hex.EncodeToString(ozet[:])

	// bridge/paket.go imzaliMetin ile birebir ayni format. Bayrak varsa v2 kullanilir.
	// Her zaman v2: son alan acilis bayragi (1 ya da 0). Bridge v2 icin 0/1 ikisini de kabul eder.
	bitAcilis := "0"
	if *acilis {
		bitAcilis = "1"
	}
	bicim := "v2"
	metin := []byte("fikoyt-eklenti-v2\n" + *eklenti + "\n" + *surum + "\n" + strings.ToLower(ozetHex) + "\n" + bitAcilis)
	m := manifest{
		Anahtar: *eklenti,
		Surum:   *surum,
		Sha256:  ozetHex,
		Imza:    base64.StdEncoding.EncodeToString(ed25519.Sign(priv, metin)),
		Bicim:   bicim,
		Acilis:  *acilis,
	}
	json_, err := json.MarshalIndent(m, "", "  ")
	kontrol(err)
	kontrol(os.WriteFile(*cikti, json_, 0644))
	fmt.Println("manifest yazildi:", *cikti)
}
