// Package zk provides the Synor ZK SDK for Go.
//
// Zero-Knowledge proof systems for ZK-Rollups and privacy.
package zk

import (
	"encoding/json"
	"fmt"
	"time"
)

// ProofSystem represents available proof system backends
type ProofSystem string

const (
	// Groth16 - smallest proofs (~192 bytes), fastest verification
	ProofSystemGroth16 ProofSystem = "groth16"
	// Plonk - universal trusted setup, medium proofs (~512 bytes)
	ProofSystemPlonk ProofSystem = "plonk"
	// Stark - no trusted setup, largest proofs (~50KB)
	ProofSystemStark ProofSystem = "stark"
)

// CircuitType represents the type of circuit
type CircuitType string

const (
	// CircuitTransfer - single transfer between accounts
	CircuitTransfer CircuitType = "transfer"
	// CircuitBatch - batch of multiple transfers
	CircuitBatch CircuitType = "batch"
	// CircuitDeposit - deposit from L1 to L2
	CircuitDeposit CircuitType = "deposit"
	// CircuitWithdraw - withdrawal from L2 to L1
	CircuitWithdraw CircuitType = "withdraw"
)

// RollupState represents the state of a rollup
type RollupState string

const (
	RollupStateActive     RollupState = "active"
	RollupStatePaused     RollupState = "paused"
	RollupStateFinalizing RollupState = "finalizing"
	RollupStateFinalized  RollupState = "finalized"
)

// ProofStatus represents the status of a proof
type ProofStatus string

const (
	ProofStatusGenerating ProofStatus = "generating"
	ProofStatusCompleted  ProofStatus = "completed"
	ProofStatusFailed     ProofStatus = "failed"
	ProofStatusVerified   ProofStatus = "verified"
)

// Proof represents a zero-knowledge proof
type Proof struct {
	ID               string      `json:"id"`
	System           ProofSystem `json:"system"`
	CircuitType      CircuitType `json:"circuit_type"`
	Data             string      `json:"data"` // Base64 encoded
	PublicInputs     []string    `json:"public_inputs"`
	Size             int         `json:"size"`
	GenerationTimeMs int64       `json:"generation_time_ms"`
	CreatedAt        int64       `json:"created_at"`
}

// VerificationKey represents a verification key for a circuit
type VerificationKey struct {
	CircuitID   string      `json:"circuit_id"`
	CircuitType CircuitType `json:"circuit_type"`
	System      ProofSystem `json:"system"`
	Data        string      `json:"data"` // Base64 encoded
	Size        int         `json:"size"`
}

// ProvingKey represents a proving key for generating proofs
type ProvingKey struct {
	CircuitID   string      `json:"circuit_id"`
	CircuitType CircuitType `json:"circuit_type"`
	System      ProofSystem `json:"system"`
	Data        string      `json:"data"` // Base64 encoded
	Size        int         `json:"size"`
}

// CircuitConfig represents circuit configuration
type CircuitConfig struct {
	Type              CircuitType            `json:"type"`
	MaxBatchSize      *int                   `json:"max_batch_size,omitempty"`
	TreeDepth         *int                   `json:"tree_depth,omitempty"`
	VerifySignatures  *bool                  `json:"verify_signatures,omitempty"`
	CustomConstraints map[string]interface{} `json:"custom_constraints,omitempty"`
}

// AccountState represents account state in the rollup
type AccountState struct {
	Address    string `json:"address"`
	Balance    string `json:"balance"`
	Nonce      uint64 `json:"nonce"`
	PubkeyHash string `json:"pubkey_hash"`
}

// Transfer represents a transfer operation
type Transfer struct {
	From      string  `json:"from"`
	To        string  `json:"to"`
	Amount    string  `json:"amount"`
	Fee       string  `json:"fee"`
	Nonce     uint64  `json:"nonce"`
	Signature *string `json:"signature,omitempty"`
}

// Deposit represents a deposit operation (L1 -> L2)
type Deposit struct {
	L1TxHash  string  `json:"l1_tx_hash"`
	Recipient string  `json:"recipient"`
	Amount    string  `json:"amount"`
	Token     *string `json:"token,omitempty"`
}

// Withdrawal represents a withdrawal operation (L2 -> L1)
type Withdrawal struct {
	Sender    string  `json:"sender"`
	Recipient string  `json:"recipient"`
	Amount    string  `json:"amount"`
	Token     *string `json:"token,omitempty"`
	Nonce     uint64  `json:"nonce"`
	Signature *string `json:"signature,omitempty"`
}

// Batch represents a rollup batch
type Batch struct {
	BatchNumber   uint64       `json:"batch_number"`
	PrevStateRoot string       `json:"prev_state_root"`
	NewStateRoot  string       `json:"new_state_root"`
	Transfers     []Transfer   `json:"transfers"`
	Deposits      []Deposit    `json:"deposits"`
	Withdrawals   []Withdrawal `json:"withdrawals"`
	Proof         *Proof       `json:"proof,omitempty"`
	Timestamp     int64        `json:"timestamp"`
}

// RollupStats represents rollup statistics
type RollupStats struct {
	CurrentBatch      uint64 `json:"current_batch"`
	TotalTransactions uint64 `json:"total_transactions"`
	TotalProofs       uint64 `json:"total_proofs"`
	AvgProofTimeMs    int64  `json:"avg_proof_time_ms"`
	StateRoot         string `json:"state_root"`
	AccountCount      uint64 `json:"account_count"`
	TVL               string `json:"tvl"`
}

// ProofRequest represents a proof generation request
type ProofRequest struct {
	CircuitType   CircuitType  `json:"circuit_type"`
	PublicInputs  []string     `json:"public_inputs"`
	PrivateInputs []string     `json:"private_inputs"`
	System        *ProofSystem `json:"system,omitempty"`
}

// VerificationResult represents proof verification result
type VerificationResult struct {
	Valid              bool    `json:"valid"`
	VerificationTimeMs int64   `json:"verification_time_ms"`
	Error              *string `json:"error,omitempty"`
}

// MerkleProof represents a merkle proof for state inclusion
type MerkleProof struct {
	Leaf    string   `json:"leaf"`
	Path    []string `json:"path"`
	Indices []int    `json:"indices"`
	Root    string   `json:"root"`
}

// CeremonyContribution represents a trusted setup ceremony contribution
type CeremonyContribution struct {
	ContributorID string `json:"contributor_id"`
	Hash          string `json:"hash"`
	Timestamp     int64  `json:"timestamp"`
	Verified      bool   `json:"verified"`
}

// TrustedSetup represents a trusted setup ceremony
type TrustedSetup struct {
	ID                string                 `json:"id"`
	CircuitType       CircuitType            `json:"circuit_type"`
	System            ProofSystem            `json:"system"`
	ContributionCount int                    `json:"contribution_count"`
	LatestHash        string                 `json:"latest_hash"`
	Complete          bool                   `json:"complete"`
	Contributions     []CeremonyContribution `json:"contributions"`
}

// Config represents ZK SDK configuration
type Config struct {
	APIKey             string
	Endpoint           string
	WSEndpoint         string
	Timeout            time.Duration
	Retries            int
	DefaultProofSystem ProofSystem
	Debug              bool
}

// DefaultConfig returns the default configuration
func DefaultConfig(apiKey string) Config {
	return Config{
		APIKey:             apiKey,
		Endpoint:           "https://zk.synor.io/v1",
		WSEndpoint:         "wss://zk.synor.io/v1/ws",
		Timeout:            60 * time.Second,
		Retries:            3,
		DefaultProofSystem: ProofSystemGroth16,
		Debug:              false,
	}
}

// Error represents a ZK SDK error
type Error struct {
	Message string
	Code    string
	Status  int
}

func (e *Error) Error() string {
	if e.Code != "" {
		return fmt.Sprintf("%s (%s)", e.Message, e.Code)
	}
	return e.Message
}

// ProofSystemInfo contains information about a proof system
type ProofSystemInfo struct {
	Name               string
	ProofSize          int
	VerificationTimeMs int
	TrustedSetup       bool
	Universal          bool
}

// GetProofSystemInfo returns information about a proof system
func GetProofSystemInfo(system ProofSystem) ProofSystemInfo {
	switch system {
	case ProofSystemGroth16:
		return ProofSystemInfo{
			Name:               "Groth16",
			ProofSize:          192,
			VerificationTimeMs: 10,
			TrustedSetup:       true,
			Universal:          false,
		}
	case ProofSystemPlonk:
		return ProofSystemInfo{
			Name:               "PLONK",
			ProofSize:          512,
			VerificationTimeMs: 15,
			TrustedSetup:       true,
			Universal:          true,
		}
	case ProofSystemStark:
		return ProofSystemInfo{
			Name:               "STARK",
			ProofSize:          50000,
			VerificationTimeMs: 30,
			TrustedSetup:       false,
			Universal:          true,
		}
	default:
		return ProofSystemInfo{}
	}
}

// Constants
const (
	MaxBatchSize      = 1000
	StateTreeDepth    = 32
	ProofExpiryBlocks = 100
)

// Helper for JSON responses
type jsonResponse struct {
	Data json.RawMessage `json:"data,omitempty"`
}

type proofsResponse struct {
	Proofs []Proof `json:"proofs"`
}

type circuitsResponse struct {
	Circuits []CircuitConfig `json:"circuits"`
}

type transactionsResponse struct {
	Transactions []Transfer `json:"transactions"`
}

type contributionsResponse struct {
	Contributions []CeremonyContribution `json:"contributions"`
}

type rootResponse struct {
	Root string `json:"root"`
}

type validResponse struct {
	Valid bool `json:"valid"`
}

type txIDResponse struct {
	TxID string `json:"tx_id"`
}

type circuitIDResponse struct {
	CircuitID string `json:"circuit_id"`
}

type serializeResponse struct {
	Data string `json:"data"`
}
