package steme

import "slices"

// LifecycleStage represents the lifecycle stage of an assertion.
//
// Assertions progress through lifecycle stages to distinguish proposals
// from decisions.
type LifecycleStage string

const (
	// LifecycleProposed is an initial proposal, idea, or RFC.
	LifecycleProposed LifecycleStage = "Proposed"

	// LifecycleUnderReview is under active review or debate.
	LifecycleUnderReview LifecycleStage = "UnderReview"

	// LifecycleApproved is accepted as current truth.
	LifecycleApproved LifecycleStage = "Approved"

	// LifecycleDeprecated was true, now superseded.
	LifecycleDeprecated LifecycleStage = "Deprecated"

	// LifecycleRejected was considered and explicitly declined.
	LifecycleRejected LifecycleStage = "Rejected"
)

// SourceClass represents the authority tier of a source.
//
// Sources are tiered from most authoritative (Regulatory, Tier 0) to
// least authoritative (Anecdotal, Tier 5).
type SourceClass string

const (
	// SourceClassRegulatory - Tier 0: Regulatory bodies (FDA, EMA, WHO)
	SourceClassRegulatory SourceClass = "Regulatory"

	// SourceClassClinical - Tier 1: Clinical trials, peer-reviewed research
	SourceClassClinical SourceClass = "Clinical"

	// SourceClassObservational - Tier 2: Observational studies, real-world evidence
	SourceClassObservational SourceClass = "Observational"

	// SourceClassExpert - Tier 3: Expert opinions, medical guidelines
	SourceClassExpert SourceClass = "Expert"

	// SourceClassCommunity - Tier 4: Curated community knowledge
	SourceClassCommunity SourceClass = "Community"

	// SourceClassAnecdotal - Tier 5: Individual reports, testimonials, social media
	SourceClassAnecdotal SourceClass = "Anecdotal"
)

// Lens represents a conflict resolution strategy.
type Lens string

const (
	// LensRecency - Latest timestamp wins
	LensRecency Lens = "Recency"

	// LensConsensus - Most common object value
	LensConsensus Lens = "Consensus"

	// LensAuthority - Weighted by agent reputation
	LensAuthority Lens = "Authority"

	// LensVoteAwareConsensus - Highest vote weight from VoteStore
	LensVoteAwareConsensus Lens = "VoteAwareConsensus"

	// LensTrustAwareAuthority - Weighted by TrustRank reputation
	LensTrustAwareAuthority Lens = "TrustAwareAuthority"
)

// ObjectValue represents the value in an assertion.
//
// This is serialized as a tagged union in JSON:
//
//	{"type": "Text", "value": "hello"}
//	{"type": "Number", "value": 42.5}
//	{"type": "Boolean", "value": true}
//	{"type": "Reference", "value": "Entity_Id"}
type ObjectValue struct {
	Type  string `json:"type"`
	Value any    `json:"value"`
}

// NewTextValue creates a text object value.
func NewTextValue(text string) ObjectValue {
	return ObjectValue{Type: "Text", Value: text}
}

// NewNumberValue creates a numeric object value.
func NewNumberValue(num float64) ObjectValue {
	return ObjectValue{Type: "Number", Value: num}
}

// NewBooleanValue creates a boolean object value.
func NewBooleanValue(val bool) ObjectValue {
	return ObjectValue{Type: "Boolean", Value: val}
}

// NewReferenceValue creates a reference object value.
func NewReferenceValue(entityID string) ObjectValue {
	return ObjectValue{Type: "Reference", Value: entityID}
}

// SignatureEntry represents an Ed25519 signature from an agent.
type SignatureEntry struct {
	// AgentID is the hex-encoded Ed25519 public key (32 bytes)
	AgentID string `json:"agent_id"`

	// Signature is the hex-encoded Ed25519 signature (64 bytes)
	Signature string `json:"signature"`

	// Timestamp is when the agent signed (Unix epoch)
	Timestamp uint64 `json:"timestamp"`

	// Version is the signature scheme version:
	//   1 = legacy: signs "{subject}:{predicate}" (default)
	//   2 = enterprise: signs BLAKE3 content hash (full tamper protection)
	Version uint8 `json:"version,omitempty"`
}

// ResolutionStatus indicates the level of agreement among claims.
type ResolutionStatus string

const (
	// ResolutionUnanimous - All assertions agree on the same value
	ResolutionUnanimous ResolutionStatus = "Unanimous"

	// ResolutionAgreed - Strong majority (>75% weight) agrees
	ResolutionAgreed ResolutionStatus = "Agreed"

	// ResolutionContested - No clear consensus; significant disagreement
	ResolutionContested ResolutionStatus = "Contested"
)

// TrustPack represents a curated list of trusted agents.
//
// Trust Packs are the "App Store for Trust" - domain experts curate lists
// of agents they vouch for, and consumers subscribe to filter consensus
// through that expertise. For example, a "Skeptical Cardio Pack" might
// contain vetted cardiologists for filtering GLP-1 side effect claims.
//
// Agents in a pack are identified by their Ed25519 public keys.
type TrustPack struct {
	// ID is the hex-encoded BLAKE3 hash of the pack content (32 bytes)
	ID string `json:"id"`

	// Name is a human-readable identifier (e.g., "Mayo_Clinic_Experts")
	Name string `json:"name"`

	// Maintainer is the hex-encoded Ed25519 public key of the pack owner (32 bytes)
	Maintainer string `json:"maintainer"`

	// Agents is a list of hex-encoded Ed25519 public keys (32 bytes each)
	Agents []string `json:"agents"`

	// CreatedAt is when the pack was created (Unix epoch)
	CreatedAt uint64 `json:"created_at"`

	// UpdatedAt is when the pack was last modified (Unix epoch)
	UpdatedAt uint64 `json:"updated_at"`
}

// NewTrustPack creates a new TrustPack with the given name and maintainer.
func NewTrustPack(name, maintainer string) TrustPack {
	return TrustPack{
		Name:       name,
		Maintainer: maintainer,
		Agents:     []string{},
	}
}

// AddAgent adds an agent to the pack if not already present.
func (tp *TrustPack) AddAgent(agentID string) {
	if slices.Contains(tp.Agents, agentID) {
		return // Already present
	}
	tp.Agents = append(tp.Agents, agentID)
}

// RemoveAgent removes an agent from the pack.
func (tp *TrustPack) RemoveAgent(agentID string) {
	for i, existing := range tp.Agents {
		if existing == agentID {
			tp.Agents = append(tp.Agents[:i], tp.Agents[i+1:]...)
			return
		}
	}
}

// ContainsAgent checks if an agent is in the pack.
func (tp *TrustPack) ContainsAgent(agentID string) bool {
	return slices.Contains(tp.Agents, agentID)
}
