package config

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

type KeyPair struct {
	KID        string `json:"kid"`
	PrivateB64 string `json:"privateB64"` // base64url(no padding)
	PublicB64  string `json:"publicB64"`  // base64url(no padding)
}

type PublicKey struct {
	KID       string `json:"kid"`
	PublicB64 string `json:"publicB64"` // base64url(no padding)
}

type Limits struct {
	MaxBodyBytes      int64 `json:"maxBodyBytes"`
	MaxClockSkewMs    int64 `json:"maxClockSkewMs"`
	DefaultTTLms      int64 `json:"defaultTTLms"`
	AntiReplayEnabled bool  `json:"antiReplayEnabled"`
}

type KongConfig struct {
	ListenAddr string `json:"listenAddr"`
	AgentURL   string `json:"agentUrl"`

	ProtoHeader string `json:"protoHeader"` // e.g. kong-agent-secure/1

	SigningKey   KeyPair   `json:"signingKey"`   // Ed25519
	DecryptKey   KeyPair   `json:"decryptKey"`   // X25519, for decrypting Agent responses
	AgentSignPub PublicKey `json:"agentSignPub"` // Ed25519
	AgentEncPub  PublicKey `json:"agentEncPub"`  // X25519

	Limits Limits `json:"limits"`
}

type AgentConfig struct {
	ListenAddr string `json:"listenAddr"`

	ProtoHeader string `json:"protoHeader"`

	SigningKey  KeyPair   `json:"signingKey"`  // Ed25519
	DecryptKey  KeyPair   `json:"decryptKey"`  // X25519, for decrypting Kong requests
	KongSignPub PublicKey `json:"kongSignPub"` // Ed25519
	KongEncPub  PublicKey `json:"kongEncPub"`  // X25519

	Limits Limits `json:"limits"`
}

func ReadKongConfig(path string) (*KongConfig, error) {
	b, err := os.ReadFile(path)
	if err != nil {
		return nil, err
	}
	var cfg KongConfig
	if err := json.Unmarshal(b, &cfg); err != nil {
		return nil, err
	}
	if err := cfg.validate(); err != nil {
		return nil, err
	}
	return &cfg, nil
}

func ReadAgentConfig(path string) (*AgentConfig, error) {
	b, err := os.ReadFile(path)
	if err != nil {
		return nil, err
	}
	var cfg AgentConfig
	if err := json.Unmarshal(b, &cfg); err != nil {
		return nil, err
	}
	if err := cfg.validate(); err != nil {
		return nil, err
	}
	return &cfg, nil
}

func (c *KongConfig) validate() error {
	if c.ListenAddr == "" {
		c.ListenAddr = ":8080"
	}
	if c.AgentURL == "" {
		return fmt.Errorf("agentUrl is required")
	}
	if c.ProtoHeader == "" {
		c.ProtoHeader = "kong-agent-secure/1"
	}
	applyDefaults(&c.Limits)
	return nil
}

func (c *AgentConfig) validate() error {
	if c.ListenAddr == "" {
		c.ListenAddr = ":8081"
	}
	if c.ProtoHeader == "" {
		c.ProtoHeader = "kong-agent-secure/1"
	}
	applyDefaults(&c.Limits)
	return nil
}

func applyDefaults(l *Limits) {
	if l.MaxBodyBytes == 0 {
		l.MaxBodyBytes = 1 << 20 // 1 MiB
	}
	if l.MaxClockSkewMs == 0 {
		l.MaxClockSkewMs = 5 * 60 * 1000
	}
	if l.DefaultTTLms == 0 {
		l.DefaultTTLms = 60 * 1000
	}
}
