package entities

import (
	"time"

	"github.com/google/uuid"
	"github.com/rwadurian/mpc-system/services/account/domain/value_objects"
)

// AccountShare represents a mapping of key share to account
// Note: This records share location, not share content
type AccountShare struct {
	ID         uuid.UUID
	AccountID  value_objects.AccountID
	ShareType  value_objects.ShareType
	PartyID    string
	PartyIndex int
	DeviceType *string
	DeviceID   *string
	CreatedAt  time.Time
	LastUsedAt *time.Time
	IsActive   bool
}

// NewAccountShare creates a new AccountShare
func NewAccountShare(
	accountID value_objects.AccountID,
	shareType value_objects.ShareType,
	partyID string,
	partyIndex int,
) *AccountShare {
	return &AccountShare{
		ID:         uuid.New(),
		AccountID:  accountID,
		ShareType:  shareType,
		PartyID:    partyID,
		PartyIndex: partyIndex,
		CreatedAt:  time.Now().UTC(),
		IsActive:   true,
	}
}

// SetDeviceInfo sets device information for user device shares
func (s *AccountShare) SetDeviceInfo(deviceType, deviceID string) {
	s.DeviceType = &deviceType
	s.DeviceID = &deviceID
}

// UpdateLastUsed updates the last used timestamp
func (s *AccountShare) UpdateLastUsed() {
	now := time.Now().UTC()
	s.LastUsedAt = &now
}

// Deactivate deactivates the share (e.g., when device is lost)
func (s *AccountShare) Deactivate() {
	s.IsActive = false
}

// Activate activates the share
func (s *AccountShare) Activate() {
	s.IsActive = true
}

// IsUserDeviceShare checks if this is a user device share
func (s *AccountShare) IsUserDeviceShare() bool {
	return s.ShareType == value_objects.ShareTypeUserDevice
}

// IsServerShare checks if this is a server share
func (s *AccountShare) IsServerShare() bool {
	return s.ShareType == value_objects.ShareTypeServer
}

// IsRecoveryShare checks if this is a recovery share
func (s *AccountShare) IsRecoveryShare() bool {
	return s.ShareType == value_objects.ShareTypeRecovery
}

// IsDelegateShare checks if this is a delegate share
func (s *AccountShare) IsDelegateShare() bool {
	return s.ShareType == value_objects.ShareTypeDelegate
}

// RequiresUserShare checks if this share type requires user to provide share for signing
func (s *AccountShare) RequiresUserShare() bool {
	return s.ShareType.RequiresUserShare()
}

// Validate validates the account share
func (s *AccountShare) Validate() error {
	if s.AccountID.IsZero() {
		return ErrShareInvalidAccountID
	}
	if !s.ShareType.IsValid() {
		return ErrShareInvalidType
	}
	if s.PartyID == "" {
		return ErrShareInvalidPartyID
	}
	if s.PartyIndex < 0 {
		return ErrShareInvalidPartyIndex
	}
	return nil
}

// AccountShare errors
var (
	ErrShareInvalidAccountID  = &AccountError{Code: "SHARE_INVALID_ACCOUNT_ID", Message: "invalid account ID"}
	ErrShareInvalidType       = &AccountError{Code: "SHARE_INVALID_TYPE", Message: "invalid share type"}
	ErrShareInvalidPartyID    = &AccountError{Code: "SHARE_INVALID_PARTY_ID", Message: "invalid party ID"}
	ErrShareInvalidPartyIndex = &AccountError{Code: "SHARE_INVALID_PARTY_INDEX", Message: "invalid party index"}
	ErrShareNotFound          = &AccountError{Code: "SHARE_NOT_FOUND", Message: "share not found"}
)
