package main

import (
	"fmt"
	"os"
	"time"

	"git.mleku.dev/mleku/nostr/crypto/keys"
	"git.mleku.dev/mleku/nostr/encoders/hex"
	"next.orly.dev/pkg/find"
	"git.mleku.dev/mleku/nostr/interfaces/signer"
	"git.mleku.dev/mleku/nostr/interfaces/signer/p8k"
)

func main() {
	if len(os.Args) < 2 {
		printUsage()
		os.Exit(1)
	}

	command := os.Args[1]

	switch command {
	case "register":
		handleRegister()
	case "transfer":
		handleTransfer()
	case "verify-name":
		handleVerifyName()
	case "generate-key":
		handleGenerateKey()
	case "issue-cert":
		handleIssueCert()
	case "help":
		printUsage()
	default:
		fmt.Printf("Unknown command: %s\n\n", command)
		printUsage()
		os.Exit(1)
	}
}

func printUsage() {
	fmt.Println("FIND - Free Internet Name Daemon")
	fmt.Println("Usage: find <command> [options]")
	fmt.Println()
	fmt.Println("Commands:")
	fmt.Println("  register <name>              Create a registration proposal for a name")
	fmt.Println("  transfer <name> <new-owner>  Transfer a name to a new owner")
	fmt.Println("  verify-name <name>           Validate a name format")
	fmt.Println("  generate-key                 Generate a new key pair")
	fmt.Println("  issue-cert <name>            Issue a certificate for a name")
	fmt.Println("  help                         Show this help message")
	fmt.Println()
	fmt.Println("Examples:")
	fmt.Println("  find verify-name example.com")
	fmt.Println("  find register myname.nostr")
	fmt.Println("  find generate-key")
}

func handleRegister() {
	if len(os.Args) < 3 {
		fmt.Println("Usage: find register <name>")
		os.Exit(1)
	}

	name := os.Args[2]

	// Validate the name
	if err := find.ValidateName(name); err != nil {
		fmt.Printf("Invalid name: %v\n", err)
		os.Exit(1)
	}

	// Generate a key pair for this example
	// In production, this would load from a secure keystore
	signer, err := p8k.New()
	if err != nil {
		fmt.Printf("Failed to create signer: %v\n", err)
		os.Exit(1)
	}

	if err := signer.Generate(); err != nil {
		fmt.Printf("Failed to generate key: %v\n", err)
		os.Exit(1)
	}

	// Create registration proposal
	proposal, err := find.NewRegistrationProposal(name, find.ActionRegister, signer)
	if err != nil {
		fmt.Printf("Failed to create proposal: %v\n", err)
		os.Exit(1)
	}

	fmt.Printf("Registration Proposal Created\n")
	fmt.Printf("==============================\n")
	fmt.Printf("Name:       %s\n", name)
	fmt.Printf("Pubkey:     %s\n", hex.Enc(signer.Pub()))
	fmt.Printf("Event ID:   %s\n", hex.Enc(proposal.GetIDBytes()))
	fmt.Printf("Kind:       %d\n", proposal.Kind)
	fmt.Printf("Created At: %s\n", time.Unix(proposal.CreatedAt, 0))
	fmt.Printf("\nEvent JSON:\n")
	json := proposal.Marshal(nil)
	fmt.Println(string(json))
}

func handleTransfer() {
	if len(os.Args) < 4 {
		fmt.Println("Usage: find transfer <name> <new-owner-pubkey>")
		os.Exit(1)
	}

	name := os.Args[2]
	newOwnerPubkey := os.Args[3]

	// Validate the name
	if err := find.ValidateName(name); err != nil {
		fmt.Printf("Invalid name: %v\n", err)
		os.Exit(1)
	}

	// Generate current owner key (in production, load from keystore)
	currentOwner, err := p8k.New()
	if err != nil {
		fmt.Printf("Failed to create current owner signer: %v\n", err)
		os.Exit(1)
	}

	if err := currentOwner.Generate(); err != nil {
		fmt.Printf("Failed to generate current owner key: %v\n", err)
		os.Exit(1)
	}

	// Authorize the transfer
	prevSig, timestamp, err := find.AuthorizeTransfer(name, newOwnerPubkey, currentOwner)
	if err != nil {
		fmt.Printf("Failed to authorize transfer: %v\n", err)
		os.Exit(1)
	}

	fmt.Printf("Transfer Authorization Created\n")
	fmt.Printf("===============================\n")
	fmt.Printf("Name:           %s\n", name)
	fmt.Printf("Current Owner:  %s\n", hex.Enc(currentOwner.Pub()))
	fmt.Printf("New Owner:      %s\n", newOwnerPubkey)
	fmt.Printf("Timestamp:      %s\n", timestamp)
	fmt.Printf("Signature:      %s\n", prevSig)
	fmt.Printf("\nTo complete the transfer, the new owner must create a proposal with:")
	fmt.Printf("  prev_owner: %s\n", hex.Enc(currentOwner.Pub()))
	fmt.Printf("  prev_sig: %s\n", prevSig)
}

func handleVerifyName() {
	if len(os.Args) < 3 {
		fmt.Println("Usage: find verify-name <name>")
		os.Exit(1)
	}

	name := os.Args[2]

	// Validate the name
	if err := find.ValidateName(name); err != nil {
		fmt.Printf("❌ Invalid name: %v\n", err)
		os.Exit(1)
	}

	normalized := find.NormalizeName(name)
	isTLD := find.IsTLD(normalized)
	parent := find.GetParentDomain(normalized)

	fmt.Printf("✓ Valid name\n")
	fmt.Printf("==============\n")
	fmt.Printf("Original:   %s\n", name)
	fmt.Printf("Normalized: %s\n", normalized)
	fmt.Printf("Is TLD:     %v\n", isTLD)
	if parent != "" {
		fmt.Printf("Parent:     %s\n", parent)
	}
}

func handleGenerateKey() {
	// Generate a new key pair
	secKey, err := keys.GenerateSecretKey()
	if err != nil {
		fmt.Printf("Failed to generate secret key: %v\n", err)
		os.Exit(1)
	}

	secKeyHex := hex.Enc(secKey)
	pubKeyHex, err := keys.GetPublicKeyHex(secKeyHex)
	if err != nil {
		fmt.Printf("Failed to derive public key: %v\n", err)
		os.Exit(1)
	}

	fmt.Println("New Key Pair Generated")
	fmt.Println("======================")
	fmt.Printf("Secret Key (keep safe!): %s\n", secKeyHex)
	fmt.Printf("Public Key:              %s\n", pubKeyHex)
	fmt.Println()
	fmt.Println("⚠️  IMPORTANT: Store the secret key securely. Anyone with access to it can control your names.")
}

func handleIssueCert() {
	if len(os.Args) < 3 {
		fmt.Println("Usage: find issue-cert <name>")
		os.Exit(1)
	}

	name := os.Args[2]

	// Validate the name
	if err := find.ValidateName(name); err != nil {
		fmt.Printf("Invalid name: %v\n", err)
		os.Exit(1)
	}

	// Generate name owner key
	owner, err := p8k.New()
	if err != nil {
		fmt.Printf("Failed to create owner signer: %v\n", err)
		os.Exit(1)
	}

	if err := owner.Generate(); err != nil {
		fmt.Printf("Failed to generate owner key: %v\n", err)
		os.Exit(1)
	}

	// Generate certificate key (different from name owner)
	certSigner, err := p8k.New()
	if err != nil {
		fmt.Printf("Failed to create cert signer: %v\n", err)
		os.Exit(1)
	}

	if err := certSigner.Generate(); err != nil {
		fmt.Printf("Failed to generate cert key: %v\n", err)
		os.Exit(1)
	}

	certPubkey := hex.Enc(certSigner.Pub())

	// Generate 3 witness signers (in production, these would be separate services)
	var witnesses []signer.I
	for i := 0; i < 3; i++ {
		witness, err := p8k.New()
		if err != nil {
			fmt.Printf("Failed to create witness %d: %v\n", i, err)
			os.Exit(1)
		}

		if err := witness.Generate(); err != nil {
			fmt.Printf("Failed to generate witness %d key: %v\n", i, err)
			os.Exit(1)
		}

		witnesses = append(witnesses, witness)
	}

	// Issue certificate (90 day validity)
	cert, err := find.IssueCertificate(name, certPubkey, find.CertificateValidity, owner, witnesses)
	if err != nil {
		fmt.Printf("Failed to issue certificate: %v\n", err)
		os.Exit(1)
	}

	fmt.Printf("Certificate Issued\n")
	fmt.Printf("==================\n")
	fmt.Printf("Name:          %s\n", cert.Name)
	fmt.Printf("Cert Pubkey:   %s\n", cert.CertPubkey)
	fmt.Printf("Valid From:    %s\n", cert.ValidFrom)
	fmt.Printf("Valid Until:   %s\n", cert.ValidUntil)
	fmt.Printf("Challenge:     %s\n", cert.Challenge)
	fmt.Printf("Witnesses:     %d\n", len(cert.Witnesses))
	fmt.Printf("Algorithm:     %s\n", cert.Algorithm)
	fmt.Printf("Usage:         %s\n", cert.Usage)

	fmt.Printf("\nWitness Pubkeys:\n")
	for i, w := range cert.Witnesses {
		fmt.Printf("  %d: %s\n", i+1, w.Pubkey)
	}
}
