// Package ucan provides UCAN v1.0.0-rc.1 compliant authorization
// for the Sonr network using the official go-ucan library.
//
// This package wraps code.sonr.org/go/ucan to provide:
//   - Delegation creation and validation
//   - Invocation creation and validation
//   - Policy evaluation
//   - Sonr-specific capability types (vault, did, dwn)
//
// UCAN Envelope Format (DAG-CBOR):
//
//	[
//	  Signature,  // Varsig-encoded signature
//	  {
//	    "h": VarsigHeader,  // Algorithm metadata
//	    "ucan/dlg@1.0.0-rc.1": DelegationPayload  // or "ucan/inv@1.0.0-rc.1"
//	  }
//	]
package ucan

import (
	"code.sonr.org/go/ucan/pkg/command"
	"code.sonr.org/go/ucan/pkg/policy"
	"code.sonr.org/go/ucan/token/delegation"
	"code.sonr.org/go/ucan/token/invocation"
)

// Re-export key types from go-ucan for convenience.
// Users should import this package instead of go-ucan directly
// for Sonr-specific functionality.
type (
	// Delegation is an immutable UCAN delegation token.
	Delegation = delegation.Token

	// Invocation is an immutable UCAN invocation token.
	Invocation = invocation.Token

	// Command is a validated UCAN command string (e.g., "/vault/read").
	Command = command.Command

	// Policy is a list of policy statements that constrain invocation arguments.
	Policy = policy.Policy

	// Statement is a single policy statement (equality, like, and, or, etc.).
	Statement = policy.Statement

	// DelegationOption configures optional fields when creating a delegation.
	DelegationOption = delegation.Option

	// InvocationOption configures optional fields when creating an invocation.
	InvocationOption = invocation.Option
)

// Re-export constructors
var (
	// NewDelegation creates a delegation: "(issuer) allows (audience) to perform (cmd+pol) on (subject)".
	NewDelegation = delegation.New

	// NewRootDelegation creates a root delegation where subject == issuer.
	NewRootDelegation = delegation.Root

	// NewPowerlineDelegation creates a powerline delegation (subject = nil).
	// Powerline automatically delegates all future delegations regardless of subject.
	NewPowerlineDelegation = delegation.Powerline

	// NewInvocation creates an invocation: "(issuer) executes (command) on (subject)".
	NewInvocation = invocation.New

	// ParseCommand validates and parses a command string.
	ParseCommand = command.Parse

	// MustParseCommand parses a command string, panicking on error.
	MustParseCommand = command.MustParse

	// TopCommand returns "/" - the most powerful capability (grants everything).
	TopCommand = command.Top

	// NewCommand creates a command from segments (e.g., NewCommand("vault", "read") -> "/vault/read").
	NewCommand = command.New
)

// Re-export delegation options
var (
	// WithExpiration sets the delegation's expiration time.
	WithExpiration = delegation.WithExpiration

	// WithExpirationIn sets expiration to now + duration.
	WithExpirationIn = delegation.WithExpirationIn

	// WithNotBefore sets when the delegation becomes valid.
	WithNotBefore = delegation.WithNotBefore

	// WithNotBeforeIn sets not-before to now + duration.
	WithNotBeforeIn = delegation.WithNotBeforeIn

	// WithDelegationMeta adds metadata to the delegation.
	WithDelegationMeta = delegation.WithMeta

	// WithDelegationNonce sets a custom nonce (default: random 12 bytes).
	WithDelegationNonce = delegation.WithNonce
)

// Re-export invocation options
var (
	// WithArgument adds a single argument to the invocation.
	WithArgument = invocation.WithArgument

	// WithAudience sets the invocation's audience (executor if different from subject).
	WithAudience = invocation.WithAudience

	// WithInvocationMeta adds metadata to the invocation.
	WithInvocationMeta = invocation.WithMeta

	// WithInvocationNonce sets a custom nonce.
	WithInvocationNonce = invocation.WithNonce

	// WithEmptyNonce sets an empty nonce for idempotent operations.
	WithEmptyNonce = invocation.WithEmptyNonce

	// WithInvocationExpiration sets the invocation's expiration time.
	WithInvocationExpiration = invocation.WithExpiration

	// WithInvocationExpirationIn sets expiration to now + duration.
	WithInvocationExpirationIn = invocation.WithExpirationIn

	// WithIssuedAt sets when the invocation was created.
	WithIssuedAt = invocation.WithIssuedAt

	// WithCause sets the receipt CID that enqueued this task.
	WithCause = invocation.WithCause
)

// Standard Sonr commands following UCAN v1.0.0-rc.1 command format.
// Commands must be lowercase, start with '/', and have no trailing slash.
const (
	// Vault commands
	CmdVaultRead   = "/vault/read"
	CmdVaultWrite  = "/vault/write"
	CmdVaultSign   = "/vault/sign"
	CmdVaultExport = "/vault/export"
	CmdVaultImport = "/vault/import"
	CmdVaultDelete = "/vault/delete"
	CmdVaultAdmin  = "/vault/admin"
	CmdVault       = "/vault" // Superuser - grants all vault commands

	// DID commands
	CmdDIDCreate     = "/did/create"
	CmdDIDUpdate     = "/did/update"
	CmdDIDDeactivate = "/did/deactivate"
	CmdDID           = "/did" // Superuser - grants all DID commands

	// DWN commands
	CmdDWNRecordsWrite  = "/dwn/records/write"
	CmdDWNRecordsRead   = "/dwn/records/read"
	CmdDWNRecordsDelete = "/dwn/records/delete"
	CmdDWN              = "/dwn" // Superuser - grants all DWN commands

	// UCAN meta commands
	CmdUCANRevoke = "/ucan/revoke"

	// Root command - grants everything
	CmdRoot = "/"
)

// Pre-parsed Sonr commands for convenience
var (
	VaultRead   = command.MustParse(CmdVaultRead)
	VaultWrite  = command.MustParse(CmdVaultWrite)
	VaultSign   = command.MustParse(CmdVaultSign)
	VaultExport = command.MustParse(CmdVaultExport)
	VaultImport = command.MustParse(CmdVaultImport)
	VaultDelete = command.MustParse(CmdVaultDelete)
	VaultAdmin  = command.MustParse(CmdVaultAdmin)
	Vault       = command.MustParse(CmdVault)

	DIDCreate     = command.MustParse(CmdDIDCreate)
	DIDUpdate     = command.MustParse(CmdDIDUpdate)
	DIDDeactivate = command.MustParse(CmdDIDDeactivate)
	DID           = command.MustParse(CmdDID)

	DWNRecordsWrite  = command.MustParse(CmdDWNRecordsWrite)
	DWNRecordsRead   = command.MustParse(CmdDWNRecordsRead)
	DWNRecordsDelete = command.MustParse(CmdDWNRecordsDelete)
	DWN              = command.MustParse(CmdDWN)

	UCANRevoke = command.MustParse(CmdUCANRevoke)
	Root       = command.Top()
)

// CommandSubsumes checks if parent command subsumes child command.
// A command subsumes another if the child is a path extension of parent.
// Example: "/vault" subsumes "/vault/read" and "/vault/write"
func CommandSubsumes(parent, child Command) bool {
	return parent.Covers(child)
}
