// Package kbgovernance defines the transport-neutral contract between the
// resource-domain KB runtime and AgentTeam's generic Approval control plane. Its
// commands and projections are governance ports, not Approval API DTOs.
package kbgovernance

import (
	"context"
	"time"
)

const (
	WikiGenerationSubjectType   = "kb_wiki_generation"
	WikiGenerationRequestType   = "kb_wiki_generation_request"
	WikiGenerationPayloadSchema = 1

	DecisionApproved  = "approved"
	DecisionRejected  = "rejected"
	DecisionWithdrawn = "withdrawn"

	WikiGenerationTerminalReady  = "ready"
	WikiGenerationTerminalFailed = "failed"
	WikiGenerationTerminalStale  = "stale"

	ErrorInvalidArgument = "invalid_argument"
	ErrorForbidden       = "forbidden"
	ErrorNotFound        = "not_found"
	ErrorConflict        = "conflict"
)

// GatewayError is the stable error boundary returned by AgentTeam's Approval
// gateway. It prevents AgentTeam-internal store errors from leaking into the
// resource runtime while preserving actionable domain and HTTP semantics.
type GatewayError struct {
	Kind    string
	Code    string
	Message string
}

func (err GatewayError) Error() string { return err.Message }

// WikiGenerationPayload is the immutable subject payload stored by AgentTeam's
// Approval domain. Principal identity is supplied by the authenticated call,
// not accepted from browser JSON.
type WikiGenerationPayload struct {
	SchemaVersion   int    `json:"schemaVersion"`
	WorkspaceID     string `json:"workspaceId"`
	KnowledgeBaseID string `json:"knowledgeBaseId"`
	SourceID        string `json:"sourceId"`
	SourceRevision  string `json:"sourceRevision"`
	SourceCommitSHA string `json:"sourceCommitSha"`
	Scope           string `json:"scope"`
	Language        string `json:"language"`
	Reason          string `json:"reason,omitempty"`
	RequesterID     string `json:"requesterId"`
	IdempotencyKey  string `json:"idempotencyKey"`
}

// PrepareWikiGenerationCommand asks the resource-domain KB authority to derive
// a canonical wiki-generation approval subject from authenticated request
// facts. The authority resolves the source commit and validates workspace, KB,
// source, scope, and requester relationships rather than trusting caller JSON.
type PrepareWikiGenerationCommand struct {
	WorkspaceID     string
	KnowledgeBaseID string
	SourceID        string
	SourceRevision  string
	Scope           string
	Language        string
	Reason          string
	RequesterID     string
	IdempotencyKey  string
	CorrelationID   string
	Now             time.Time
}

// PreparedWikiGeneration is the immutable subject envelope produced by the KB
// authority for AgentTeam Approval. PayloadJSON and PayloadDigest bind exactly the
// reviewed facts; this is not a worker job or API response representation.
type PreparedWikiGeneration struct {
	Payload       WikiGenerationPayload
	PayloadJSON   []byte
	PayloadDigest string
	CorrelationID string
	PreparedAt    time.Time
}

// RecordWikiApprovalCommand returns the Approval instance identity and version
// allocated by AgentTeam to the resource authority so it can durably correlate the
// prepared wiki-generation request.
type RecordWikiApprovalCommand struct {
	RequestID       string
	ApprovalID      string
	ApprovalVersion int64
	Prepared        PreparedWikiGeneration
	Now             time.Time
}

// WikiGenerationState is the resource authority's persisted governance state
// projected across the Approval gateway. It is not AgentTeam's generic Approval
// model; DomainVersion and Stale describe the KB request aggregate.
type WikiGenerationState struct {
	RequestID       string
	ApprovalID      string
	ApprovalVersion int64
	Status          string
	DomainVersion   int64
	Stale           bool
}

// ResolveWikiApprovalCommand carries an authoritative AgentTeam Approval decision
// back to the KB authority. The authority uses the expected Approval version,
// authenticated actor, and decision id to enforce idempotency and freshness.
type ResolveWikiApprovalCommand struct {
	WorkspaceID      string
	ApprovalID       string
	ApprovalVersion  int64
	ActorPrincipalID string
	ClientDecisionID string
	Decision         string
	Reason           string
	Now              time.Time
}

// SubmitWikiGenerationCommand carries an already-authenticated MeshX user and
// a payload prepared by the MeshX authority. The gateway must derive the AgentTeam
// member and approver assignments from authoritative core state.
type SubmitWikiGenerationCommand struct {
	ActorPrincipalID string
	Prepared         PreparedWikiGeneration
}

// DecideWikiGenerationCommand is the same-page review command. Assignment and
// member identities are intentionally absent; AgentTeam derives both from Actor.
type DecideWikiGenerationCommand struct {
	WorkspaceID      string
	ApprovalID       string
	ActorPrincipalID string
	ExpectedVersion  int64
	ClientDecisionID string
	Decision         string
	Reason           string
	CorrelationID    string
	Now              time.Time
}

// WithdrawWikiGenerationCommand asks AgentTeam Approval to withdraw one existing
// wiki-generation review for the authenticated actor. AgentTeam resolves membership
// and ownership; callers cannot supply those authority facts.
type WithdrawWikiGenerationCommand struct {
	WorkspaceID      string
	ApprovalID       string
	ActorPrincipalID string
	ExpectedVersion  int64
	ClientRequestID  string
	Now              time.Time
}

// WikiGenerationApprovalGateway is implemented by AgentTeam and injected into the
// embedded MeshX runtime before HTTP traffic starts.
type WikiGenerationApprovalGateway interface {
	SubmitWikiGeneration(context.Context, SubmitWikiGenerationCommand) (WikiGenerationState, error)
	DecideWikiGeneration(context.Context, DecideWikiGenerationCommand) (WikiGenerationState, error)
	WithdrawWikiGeneration(context.Context, WithdrawWikiGenerationCommand) (WikiGenerationState, error)
}

// WikiGenerationTerminal is the sanitized terminal request projection used by
// AgentTeam notifications. It never carries raw worker output or credentials.
type WikiGenerationTerminal struct {
	WorkspaceID      string
	KnowledgeBaseID  string
	SourceID         string
	SourceRevision   string
	RequestID        string
	RequesterID      string
	Status           string
	Reason           string
	ArtifactRevision string
	Version          int64
}

// InspectWikiGenerationTerminalCommand identifies the resource request whose
// terminal facts AgentTeam must re-load from the KB authority before notifying.
type InspectWikiGenerationTerminalCommand struct {
	WorkspaceID string
	RequestID   string
}

// NotifyWikiGenerationTerminalCommand asks AgentTeam to publish a notification for
// a specific terminal request version. The command intentionally carries no
// worker output or recipient identity; AgentTeam derives both authoritative facts.
type NotifyWikiGenerationTerminalCommand struct {
	WorkspaceID     string
	RequestID       string
	ExpectedVersion int64
}

// WikiGenerationTerminalGateway is implemented by AgentTeam and injected into the
// embedded worker. MeshX retains the durable retry ledger and calls this port
// only for an explicit terminal generation request.
type WikiGenerationTerminalGateway interface {
	NotifyWikiGenerationTerminal(context.Context, NotifyWikiGenerationTerminalCommand) error
}

// WikiGenerationTerminalAuthority lets AgentTeam re-load terminal facts from
// MeshX instead of trusting notification payload data supplied by a caller.
type WikiGenerationTerminalAuthority interface {
	InspectWikiGenerationTerminal(context.Context, InspectWikiGenerationTerminalCommand) (WikiGenerationTerminal, error)
}

// WikiGenerationAuthority is implemented by MeshX and consumed by AgentTeam's
// kb_wiki_generation Approval subject adapter.
type WikiGenerationAuthority interface {
	PrepareWikiGeneration(context.Context, PrepareWikiGenerationCommand) (PreparedWikiGeneration, error)
	RecordWikiGenerationApproval(context.Context, RecordWikiApprovalCommand) (WikiGenerationState, error)
	ResolveWikiGenerationApproval(context.Context, ResolveWikiApprovalCommand) (WikiGenerationState, error)
}
