package native

import (
	"encoding/binary"

	"git.marketally.com/tutus-one/tutus-chain/pkg/core/dao"
	"git.marketally.com/tutus-one/tutus-chain/pkg/core/storage"
	"git.marketally.com/tutus-one/tutus-chain/pkg/util"
)

// ARCH-005: Comprehensive Audit Logging
// Provides structured audit logging for all sensitive operations,
// supporting compliance requirements, incident investigation, and
// security monitoring.

// AuditCategory categorizes audit events.
type AuditCategory uint8

const (
	AuditCategoryAuth AuditCategory = iota
	AuditCategoryAccess
	AuditCategoryData
	AuditCategoryGovernance
	AuditCategoryFinancial
	AuditCategorySecurity
	AuditCategorySystem
	AuditCategoryCompliance
)

// AuditSeverity indicates the importance of an audit event.
type AuditSeverity uint8

const (
	AuditSeverityInfo AuditSeverity = iota
	AuditSeverityNotice
	AuditSeverityWarning
	AuditSeverityAlert
	AuditSeverityCritical
)

// AuditOutcome indicates the result of an audited operation.
type AuditOutcome uint8

const (
	AuditOutcomeSuccess AuditOutcome = iota
	AuditOutcomeFailure
	AuditOutcomeDenied
	AuditOutcomeError
	AuditOutcomePartial
)

// AuditEntry represents a single audit log entry.
type AuditEntry struct {
	// EntryID is unique identifier for this entry
	EntryID uint64
	// Timestamp is the block height when event occurred
	Timestamp uint32
	// Category classifies the event
	Category AuditCategory
	// Severity indicates importance
	Severity AuditSeverity
	// Outcome is the result of the operation
	Outcome AuditOutcome
	// ContractID identifies the originating contract
	ContractID int32
	// Actor is who performed the action
	Actor util.Uint160
	// Target is the subject of the action (if applicable)
	Target util.Uint160
	// Action is the operation performed
	Action string
	// ResourceID identifies the affected resource
	ResourceID []byte
	// Details contains additional context
	Details string
	// IPHash is hash of source IP (for off-chain correlation)
	IPHash util.Uint256
	// PreviousState is hash of state before change
	PreviousState util.Uint256
	// NewState is hash of state after change
	NewState util.Uint256
}

// AuditQuery defines parameters for searching audit logs.
type AuditQuery struct {
	// StartBlock is the earliest block to search
	StartBlock uint32
	// EndBlock is the latest block to search
	EndBlock uint32
	// Category filters by event category (nil = all)
	Category *AuditCategory
	// Severity filters by minimum severity
	MinSeverity *AuditSeverity
	// Actor filters by actor address
	Actor *util.Uint160
	// Target filters by target address
	Target *util.Uint160
	// ContractID filters by contract
	ContractID *int32
	// Limit is maximum results to return
	Limit int
	// Offset is the starting position
	Offset int
}

// Storage prefixes for audit logging.
const (
	auditPrefixEntry       byte = 0xA0 // entryID -> AuditEntry
	auditPrefixByBlock     byte = 0xA1 // block + entryID -> exists
	auditPrefixByActor     byte = 0xA2 // actor + block + entryID -> exists
	auditPrefixByTarget    byte = 0xA3 // target + block + entryID -> exists
	auditPrefixByCategory  byte = 0xA4 // category + block + entryID -> exists
	auditPrefixBySeverity  byte = 0xA5 // severity + block + entryID -> exists
	auditPrefixByContract  byte = 0xA6 // contractID + block + entryID -> exists
	auditPrefixCounter     byte = 0xAF // -> next entryID
	auditPrefixRetention   byte = 0xAE // -> retention config
)

// AuditLogger provides comprehensive audit logging.
type AuditLogger struct {
	contractID int32
}

// NewAuditLogger creates a new audit logger.
func NewAuditLogger(contractID int32) *AuditLogger {
	return &AuditLogger{contractID: contractID}
}

// Log records an audit entry.
func (al *AuditLogger) Log(d *dao.Simple, entry *AuditEntry) uint64 {
	// Get and increment entry counter
	entry.EntryID = al.getNextEntryID(d)

	// Store main entry
	al.putEntry(d, entry)

	// Create indices for efficient querying
	al.indexEntry(d, entry)

	return entry.EntryID
}

// LogAuth logs an authentication event.
func (al *AuditLogger) LogAuth(d *dao.Simple, actor util.Uint160, action string, outcome AuditOutcome,
	blockHeight uint32, details string) uint64 {
	return al.Log(d, &AuditEntry{
		Timestamp:  blockHeight,
		Category:   AuditCategoryAuth,
		Severity:   al.severityForOutcome(outcome, AuditCategoryAuth),
		Outcome:    outcome,
		Actor:      actor,
		Action:     action,
		Details:    details,
	})
}

// LogAccess logs a data access event.
func (al *AuditLogger) LogAccess(d *dao.Simple, actor, target util.Uint160, action string,
	resourceID []byte, outcome AuditOutcome, blockHeight uint32) uint64 {
	return al.Log(d, &AuditEntry{
		Timestamp:  blockHeight,
		Category:   AuditCategoryAccess,
		Severity:   al.severityForOutcome(outcome, AuditCategoryAccess),
		Outcome:    outcome,
		Actor:      actor,
		Target:     target,
		Action:     action,
		ResourceID: resourceID,
	})
}

// LogDataChange logs a data modification event.
func (al *AuditLogger) LogDataChange(d *dao.Simple, actor util.Uint160, contractID int32,
	action string, resourceID []byte, prevState, newState util.Uint256, blockHeight uint32) uint64 {
	return al.Log(d, &AuditEntry{
		Timestamp:     blockHeight,
		Category:      AuditCategoryData,
		Severity:      AuditSeverityNotice,
		Outcome:       AuditOutcomeSuccess,
		ContractID:    contractID,
		Actor:         actor,
		Action:        action,
		ResourceID:    resourceID,
		PreviousState: prevState,
		NewState:      newState,
	})
}

// LogGovernance logs a governance action.
func (al *AuditLogger) LogGovernance(d *dao.Simple, actor util.Uint160, action string,
	details string, outcome AuditOutcome, blockHeight uint32) uint64 {
	severity := AuditSeverityNotice
	if outcome == AuditOutcomeSuccess {
		severity = AuditSeverityWarning // Governance changes warrant attention
	}

	return al.Log(d, &AuditEntry{
		Timestamp:  blockHeight,
		Category:   AuditCategoryGovernance,
		Severity:   severity,
		Outcome:    outcome,
		Actor:      actor,
		Action:     action,
		Details:    details,
	})
}

// LogFinancial logs a financial transaction.
func (al *AuditLogger) LogFinancial(d *dao.Simple, actor, target util.Uint160,
	action string, resourceID []byte, outcome AuditOutcome, blockHeight uint32) uint64 {
	return al.Log(d, &AuditEntry{
		Timestamp:  blockHeight,
		Category:   AuditCategoryFinancial,
		Severity:   AuditSeverityNotice,
		Outcome:    outcome,
		Actor:      actor,
		Target:     target,
		Action:     action,
		ResourceID: resourceID,
	})
}

// LogSecurity logs a security-related event.
func (al *AuditLogger) LogSecurity(d *dao.Simple, actor util.Uint160, action string,
	severity AuditSeverity, outcome AuditOutcome, details string, blockHeight uint32) uint64 {
	return al.Log(d, &AuditEntry{
		Timestamp:  blockHeight,
		Category:   AuditCategorySecurity,
		Severity:   severity,
		Outcome:    outcome,
		Actor:      actor,
		Action:     action,
		Details:    details,
	})
}

// LogCompliance logs a compliance-related event.
func (al *AuditLogger) LogCompliance(d *dao.Simple, actor, target util.Uint160,
	action string, details string, blockHeight uint32) uint64 {
	return al.Log(d, &AuditEntry{
		Timestamp:  blockHeight,
		Category:   AuditCategoryCompliance,
		Severity:   AuditSeverityNotice,
		Outcome:    AuditOutcomeSuccess,
		Actor:      actor,
		Target:     target,
		Action:     action,
		Details:    details,
	})
}

// LogRightsAccess logs access to rights-protected resources.
func (al *AuditLogger) LogRightsAccess(d *dao.Simple, actor, subject util.Uint160,
	rightID uint8, action string, outcome AuditOutcome, blockHeight uint32) uint64 {
	return al.Log(d, &AuditEntry{
		Timestamp:  blockHeight,
		Category:   AuditCategoryCompliance,
		Severity:   AuditSeverityWarning,
		Outcome:    outcome,
		Actor:      actor,
		Target:     subject,
		Action:     action,
		ResourceID: []byte{rightID},
	})
}

// GetEntry retrieves an audit entry by ID.
func (al *AuditLogger) GetEntry(d *dao.Simple, entryID uint64) *AuditEntry {
	key := al.makeEntryKey(entryID)
	si := d.GetStorageItem(al.contractID, key)
	if si == nil {
		return nil
	}
	return al.deserializeEntry(si)
}

// Query searches audit logs based on query parameters.
func (al *AuditLogger) Query(d *dao.Simple, query *AuditQuery) []*AuditEntry {
	var entries []*AuditEntry
	var entryIDs []uint64

	// Choose the most selective index
	if query.Actor != nil {
		entryIDs = al.queryByActor(d, *query.Actor, query.StartBlock, query.EndBlock, query.Limit+query.Offset)
	} else if query.Target != nil {
		entryIDs = al.queryByTarget(d, *query.Target, query.StartBlock, query.EndBlock, query.Limit+query.Offset)
	} else if query.Category != nil {
		entryIDs = al.queryByCategory(d, *query.Category, query.StartBlock, query.EndBlock, query.Limit+query.Offset)
	} else if query.MinSeverity != nil {
		entryIDs = al.queryBySeverity(d, *query.MinSeverity, query.StartBlock, query.EndBlock, query.Limit+query.Offset)
	} else {
		entryIDs = al.queryByBlock(d, query.StartBlock, query.EndBlock, query.Limit+query.Offset)
	}

	// Apply offset and limit
	start := query.Offset
	if start > len(entryIDs) {
		return entries
	}
	end := start + query.Limit
	if end > len(entryIDs) {
		end = len(entryIDs)
	}

	// Fetch entries
	for _, id := range entryIDs[start:end] {
		if entry := al.GetEntry(d, id); entry != nil {
			// Apply additional filters
			if al.matchesQuery(entry, query) {
				entries = append(entries, entry)
			}
		}
	}

	return entries
}

// GetEntriesForActor retrieves audit entries for a specific actor.
func (al *AuditLogger) GetEntriesForActor(d *dao.Simple, actor util.Uint160, limit int) []*AuditEntry {
	return al.Query(d, &AuditQuery{
		Actor: &actor,
		Limit: limit,
	})
}

// GetEntriesForTarget retrieves audit entries for a specific target.
func (al *AuditLogger) GetEntriesForTarget(d *dao.Simple, target util.Uint160, limit int) []*AuditEntry {
	return al.Query(d, &AuditQuery{
		Target: &target,
		Limit:  limit,
	})
}

// GetSecurityAlerts retrieves high-severity security events.
func (al *AuditLogger) GetSecurityAlerts(d *dao.Simple, startBlock, endBlock uint32, limit int) []*AuditEntry {
	severity := AuditSeverityAlert
	category := AuditCategorySecurity
	return al.Query(d, &AuditQuery{
		StartBlock:  startBlock,
		EndBlock:    endBlock,
		Category:    &category,
		MinSeverity: &severity,
		Limit:       limit,
	})
}

// GetComplianceLog retrieves compliance-related entries for reporting.
func (al *AuditLogger) GetComplianceLog(d *dao.Simple, startBlock, endBlock uint32, limit int) []*AuditEntry {
	category := AuditCategoryCompliance
	return al.Query(d, &AuditQuery{
		StartBlock: startBlock,
		EndBlock:   endBlock,
		Category:   &category,
		Limit:      limit,
	})
}

// severityForOutcome determines severity based on outcome and category.
func (al *AuditLogger) severityForOutcome(outcome AuditOutcome, category AuditCategory) AuditSeverity {
	switch outcome {
	case AuditOutcomeSuccess:
		return AuditSeverityInfo
	case AuditOutcomeFailure:
		return AuditSeverityNotice
	case AuditOutcomeDenied:
		if category == AuditCategorySecurity || category == AuditCategoryAuth {
			return AuditSeverityAlert
		}
		return AuditSeverityWarning
	case AuditOutcomeError:
		return AuditSeverityWarning
	default:
		return AuditSeverityInfo
	}
}

// matchesQuery checks if an entry matches additional query filters.
func (al *AuditLogger) matchesQuery(entry *AuditEntry, query *AuditQuery) bool {
	if query.Category != nil && entry.Category != *query.Category {
		return false
	}
	if query.MinSeverity != nil && entry.Severity < *query.MinSeverity {
		return false
	}
	if query.ContractID != nil && entry.ContractID != *query.ContractID {
		return false
	}
	if query.Actor != nil && entry.Actor != *query.Actor {
		return false
	}
	if query.Target != nil && entry.Target != *query.Target {
		return false
	}
	return true
}

// Index query methods.
func (al *AuditLogger) queryByBlock(d *dao.Simple, startBlock, endBlock uint32, limit int) []uint64 {
	var ids []uint64
	prefix := []byte{auditPrefixByBlock}

	d.Seek(al.contractID, storage.SeekRange{Prefix: prefix}, func(k, v []byte) bool {
		if len(k) < 12 {
			return true
		}
		block := binary.BigEndian.Uint32(k[0:4])
		if block < startBlock || (endBlock > 0 && block > endBlock) {
			return true
		}
		entryID := binary.BigEndian.Uint64(k[4:12])
		ids = append(ids, entryID)
		return len(ids) < limit
	})

	return ids
}

func (al *AuditLogger) queryByActor(d *dao.Simple, actor util.Uint160, startBlock, endBlock uint32, limit int) []uint64 {
	var ids []uint64
	prefix := make([]byte, 21)
	prefix[0] = auditPrefixByActor
	copy(prefix[1:], actor.BytesBE())

	d.Seek(al.contractID, storage.SeekRange{Prefix: prefix}, func(k, v []byte) bool {
		if len(k) < 12 {
			return true
		}
		block := binary.BigEndian.Uint32(k[0:4])
		if block < startBlock || (endBlock > 0 && block > endBlock) {
			return true
		}
		entryID := binary.BigEndian.Uint64(k[4:12])
		ids = append(ids, entryID)
		return len(ids) < limit
	})

	return ids
}

func (al *AuditLogger) queryByTarget(d *dao.Simple, target util.Uint160, startBlock, endBlock uint32, limit int) []uint64 {
	var ids []uint64
	prefix := make([]byte, 21)
	prefix[0] = auditPrefixByTarget
	copy(prefix[1:], target.BytesBE())

	d.Seek(al.contractID, storage.SeekRange{Prefix: prefix}, func(k, v []byte) bool {
		if len(k) < 12 {
			return true
		}
		block := binary.BigEndian.Uint32(k[0:4])
		if block < startBlock || (endBlock > 0 && block > endBlock) {
			return true
		}
		entryID := binary.BigEndian.Uint64(k[4:12])
		ids = append(ids, entryID)
		return len(ids) < limit
	})

	return ids
}

func (al *AuditLogger) queryByCategory(d *dao.Simple, category AuditCategory, startBlock, endBlock uint32, limit int) []uint64 {
	var ids []uint64
	prefix := []byte{auditPrefixByCategory, byte(category)}

	d.Seek(al.contractID, storage.SeekRange{Prefix: prefix}, func(k, v []byte) bool {
		if len(k) < 12 {
			return true
		}
		block := binary.BigEndian.Uint32(k[0:4])
		if block < startBlock || (endBlock > 0 && block > endBlock) {
			return true
		}
		entryID := binary.BigEndian.Uint64(k[4:12])
		ids = append(ids, entryID)
		return len(ids) < limit
	})

	return ids
}

func (al *AuditLogger) queryBySeverity(d *dao.Simple, minSeverity AuditSeverity, startBlock, endBlock uint32, limit int) []uint64 {
	var ids []uint64

	for sev := minSeverity; sev <= AuditSeverityCritical; sev++ {
		prefix := []byte{auditPrefixBySeverity, byte(sev)}

		d.Seek(al.contractID, storage.SeekRange{Prefix: prefix}, func(k, v []byte) bool {
			if len(k) < 12 {
				return true
			}
			block := binary.BigEndian.Uint32(k[0:4])
			if block < startBlock || (endBlock > 0 && block > endBlock) {
				return true
			}
			entryID := binary.BigEndian.Uint64(k[4:12])
			ids = append(ids, entryID)
			return len(ids) < limit
		})

		if len(ids) >= limit {
			break
		}
	}

	return ids
}

// Storage key helpers.
func (al *AuditLogger) makeEntryKey(entryID uint64) []byte {
	key := make([]byte, 9)
	key[0] = auditPrefixEntry
	binary.BigEndian.PutUint64(key[1:], entryID)
	return key
}

func (al *AuditLogger) getNextEntryID(d *dao.Simple) uint64 {
	key := []byte{auditPrefixCounter}
	si := d.GetStorageItem(al.contractID, key)

	var nextID uint64 = 1
	if si != nil && len(si) >= 8 {
		nextID = binary.BigEndian.Uint64(si) + 1
	}

	data := make([]byte, 8)
	binary.BigEndian.PutUint64(data, nextID)
	d.PutStorageItem(al.contractID, key, data)

	return nextID
}

func (al *AuditLogger) putEntry(d *dao.Simple, entry *AuditEntry) {
	key := al.makeEntryKey(entry.EntryID)
	data := al.serializeEntry(entry)
	d.PutStorageItem(al.contractID, key, data)
}

func (al *AuditLogger) indexEntry(d *dao.Simple, entry *AuditEntry) {
	// Index by block
	blockKey := make([]byte, 13)
	blockKey[0] = auditPrefixByBlock
	binary.BigEndian.PutUint32(blockKey[1:5], entry.Timestamp)
	binary.BigEndian.PutUint64(blockKey[5:13], entry.EntryID)
	d.PutStorageItem(al.contractID, blockKey, []byte{1})

	// Index by actor
	if entry.Actor != (util.Uint160{}) {
		actorKey := make([]byte, 33)
		actorKey[0] = auditPrefixByActor
		copy(actorKey[1:21], entry.Actor.BytesBE())
		binary.BigEndian.PutUint32(actorKey[21:25], entry.Timestamp)
		binary.BigEndian.PutUint64(actorKey[25:33], entry.EntryID)
		d.PutStorageItem(al.contractID, actorKey, []byte{1})
	}

	// Index by target
	if entry.Target != (util.Uint160{}) {
		targetKey := make([]byte, 33)
		targetKey[0] = auditPrefixByTarget
		copy(targetKey[1:21], entry.Target.BytesBE())
		binary.BigEndian.PutUint32(targetKey[21:25], entry.Timestamp)
		binary.BigEndian.PutUint64(targetKey[25:33], entry.EntryID)
		d.PutStorageItem(al.contractID, targetKey, []byte{1})
	}

	// Index by category
	catKey := make([]byte, 14)
	catKey[0] = auditPrefixByCategory
	catKey[1] = byte(entry.Category)
	binary.BigEndian.PutUint32(catKey[2:6], entry.Timestamp)
	binary.BigEndian.PutUint64(catKey[6:14], entry.EntryID)
	d.PutStorageItem(al.contractID, catKey, []byte{1})

	// Index by severity
	sevKey := make([]byte, 14)
	sevKey[0] = auditPrefixBySeverity
	sevKey[1] = byte(entry.Severity)
	binary.BigEndian.PutUint32(sevKey[2:6], entry.Timestamp)
	binary.BigEndian.PutUint64(sevKey[6:14], entry.EntryID)
	d.PutStorageItem(al.contractID, sevKey, []byte{1})

	// Index by contract
	if entry.ContractID != 0 {
		contractKey := make([]byte, 17)
		contractKey[0] = auditPrefixByContract
		binary.BigEndian.PutUint32(contractKey[1:5], uint32(entry.ContractID))
		binary.BigEndian.PutUint32(contractKey[5:9], entry.Timestamp)
		binary.BigEndian.PutUint64(contractKey[9:17], entry.EntryID)
		d.PutStorageItem(al.contractID, contractKey, []byte{1})
	}
}

// Serialization helpers.
func (al *AuditLogger) serializeEntry(e *AuditEntry) []byte {
	actionBytes := []byte(e.Action)
	detailsBytes := []byte(e.Details)

	size := 8 + 4 + 1 + 1 + 1 + 4 + 20 + 20 +
		4 + len(actionBytes) +
		4 + len(e.ResourceID) +
		4 + len(detailsBytes) +
		32 + 32 + 32

	data := make([]byte, size)
	offset := 0

	binary.BigEndian.PutUint64(data[offset:], e.EntryID)
	offset += 8
	binary.BigEndian.PutUint32(data[offset:], e.Timestamp)
	offset += 4
	data[offset] = byte(e.Category)
	offset++
	data[offset] = byte(e.Severity)
	offset++
	data[offset] = byte(e.Outcome)
	offset++
	binary.BigEndian.PutUint32(data[offset:], uint32(e.ContractID))
	offset += 4
	copy(data[offset:], e.Actor.BytesBE())
	offset += 20
	copy(data[offset:], e.Target.BytesBE())
	offset += 20

	binary.BigEndian.PutUint32(data[offset:], uint32(len(actionBytes)))
	offset += 4
	copy(data[offset:], actionBytes)
	offset += len(actionBytes)

	binary.BigEndian.PutUint32(data[offset:], uint32(len(e.ResourceID)))
	offset += 4
	copy(data[offset:], e.ResourceID)
	offset += len(e.ResourceID)

	binary.BigEndian.PutUint32(data[offset:], uint32(len(detailsBytes)))
	offset += 4
	copy(data[offset:], detailsBytes)
	offset += len(detailsBytes)

	copy(data[offset:], e.IPHash[:])
	offset += 32
	copy(data[offset:], e.PreviousState[:])
	offset += 32
	copy(data[offset:], e.NewState[:])

	return data
}

func (al *AuditLogger) deserializeEntry(data []byte) *AuditEntry {
	if len(data) < 60 {
		return nil
	}

	e := &AuditEntry{}
	offset := 0

	e.EntryID = binary.BigEndian.Uint64(data[offset:])
	offset += 8
	e.Timestamp = binary.BigEndian.Uint32(data[offset:])
	offset += 4
	e.Category = AuditCategory(data[offset])
	offset++
	e.Severity = AuditSeverity(data[offset])
	offset++
	e.Outcome = AuditOutcome(data[offset])
	offset++
	e.ContractID = int32(binary.BigEndian.Uint32(data[offset:]))
	offset += 4
	e.Actor, _ = util.Uint160DecodeBytesBE(data[offset : offset+20])
	offset += 20
	e.Target, _ = util.Uint160DecodeBytesBE(data[offset : offset+20])
	offset += 20

	if offset+4 > len(data) {
		return nil
	}
	actionLen := binary.BigEndian.Uint32(data[offset:])
	offset += 4
	if offset+int(actionLen) > len(data) {
		return nil
	}
	e.Action = string(data[offset : offset+int(actionLen)])
	offset += int(actionLen)

	if offset+4 > len(data) {
		return nil
	}
	resourceLen := binary.BigEndian.Uint32(data[offset:])
	offset += 4
	if offset+int(resourceLen) > len(data) {
		return nil
	}
	e.ResourceID = make([]byte, resourceLen)
	copy(e.ResourceID, data[offset:offset+int(resourceLen)])
	offset += int(resourceLen)

	if offset+4 > len(data) {
		return nil
	}
	detailsLen := binary.BigEndian.Uint32(data[offset:])
	offset += 4
	if offset+int(detailsLen) > len(data) {
		return nil
	}
	e.Details = string(data[offset : offset+int(detailsLen)])
	offset += int(detailsLen)

	if offset+96 > len(data) {
		return e // Return partial if hashes missing
	}
	copy(e.IPHash[:], data[offset:offset+32])
	offset += 32
	copy(e.PreviousState[:], data[offset:offset+32])
	offset += 32
	copy(e.NewState[:], data[offset:offset+32])

	return e
}

// StandardAuditActions defines common audit action names.
var StandardAuditActions = struct {
	// Auth actions
	AuthLogin         string
	AuthLogout        string
	AuthFailedLogin   string
	AuthRoleAssigned  string
	AuthRoleRevoked   string

	// Access actions
	AccessRead        string
	AccessWrite       string
	AccessDelete      string
	AccessDenied      string

	// Financial actions
	FinTransfer       string
	FinMint           string
	FinBurn           string
	FinInvest         string
	FinWithdraw       string

	// Governance actions
	GovProposalCreate string
	GovVote           string
	GovProposalPass   string
	GovProposalReject string

	// Security actions
	SecCircuitTrip    string
	SecRollback       string
	SecInvariantFail  string
	SecRightsRestrict string
}{
	AuthLogin:         "auth.login",
	AuthLogout:        "auth.logout",
	AuthFailedLogin:   "auth.failed_login",
	AuthRoleAssigned:  "auth.role_assigned",
	AuthRoleRevoked:   "auth.role_revoked",
	AccessRead:        "access.read",
	AccessWrite:       "access.write",
	AccessDelete:      "access.delete",
	AccessDenied:      "access.denied",
	FinTransfer:       "financial.transfer",
	FinMint:           "financial.mint",
	FinBurn:           "financial.burn",
	FinInvest:         "financial.invest",
	FinWithdraw:       "financial.withdraw",
	GovProposalCreate: "governance.proposal_create",
	GovVote:           "governance.vote",
	GovProposalPass:   "governance.proposal_pass",
	GovProposalReject: "governance.proposal_reject",
	SecCircuitTrip:    "security.circuit_trip",
	SecRollback:       "security.rollback",
	SecInvariantFail:  "security.invariant_fail",
	SecRightsRestrict: "security.rights_restrict",
}
