package ports

import (
	"context"

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

// CreateAccountInput represents input for creating an account
type CreateAccountInput struct {
	Username        string
	Email           string
	Phone           *string
	PublicKey       []byte
	KeygenSessionID uuid.UUID
	ThresholdN      int
	ThresholdT      int
	Shares          []ShareInput
}

// ShareInput represents input for a key share
type ShareInput struct {
	ShareType  value_objects.ShareType
	PartyID    string
	PartyIndex int
	DeviceType *string
	DeviceID   *string
}

// CreateAccountOutput represents output from creating an account
type CreateAccountOutput struct {
	Account *entities.Account
	Shares  []*entities.AccountShare
}

// CreateAccountPort defines the input port for creating accounts
type CreateAccountPort interface {
	Execute(ctx context.Context, input CreateAccountInput) (*CreateAccountOutput, error)
}

// GetAccountInput represents input for getting an account
type GetAccountInput struct {
	AccountID *value_objects.AccountID
	Username  *string
	Email     *string
}

// GetAccountOutput represents output from getting an account
type GetAccountOutput struct {
	Account *entities.Account
	Shares  []*entities.AccountShare
}

// GetAccountPort defines the input port for getting accounts
type GetAccountPort interface {
	Execute(ctx context.Context, input GetAccountInput) (*GetAccountOutput, error)
}

// LoginInput represents input for login
type LoginInput struct {
	Username  string
	Challenge []byte
	Signature []byte
}

// LoginOutput represents output from login
type LoginOutput struct {
	Account      *entities.Account
	AccessToken  string
	RefreshToken string
}

// LoginPort defines the input port for login
type LoginPort interface {
	Execute(ctx context.Context, input LoginInput) (*LoginOutput, error)
}

// InitiateRecoveryInput represents input for initiating recovery
type InitiateRecoveryInput struct {
	AccountID    value_objects.AccountID
	RecoveryType value_objects.RecoveryType
	OldShareType *value_objects.ShareType
}

// InitiateRecoveryOutput represents output from initiating recovery
type InitiateRecoveryOutput struct {
	RecoverySession *entities.RecoverySession
}

// InitiateRecoveryPort defines the input port for initiating recovery
type InitiateRecoveryPort interface {
	Execute(ctx context.Context, input InitiateRecoveryInput) (*InitiateRecoveryOutput, error)
}

// CompleteRecoveryInput represents input for completing recovery
type CompleteRecoveryInput struct {
	RecoverySessionID  string
	NewPublicKey       []byte
	NewKeygenSessionID uuid.UUID
	NewShares          []ShareInput
}

// CompleteRecoveryOutput represents output from completing recovery
type CompleteRecoveryOutput struct {
	Account *entities.Account
}

// CompleteRecoveryPort defines the input port for completing recovery
type CompleteRecoveryPort interface {
	Execute(ctx context.Context, input CompleteRecoveryInput) (*CompleteRecoveryOutput, error)
}

// UpdateAccountInput represents input for updating an account
type UpdateAccountInput struct {
	AccountID           value_objects.AccountID
	Phone               *string
	SigningParties      []string // Set/update signing parties (nil means no change)
	ClearSigningParties bool     // If true, clear signing parties configuration
}

// UpdateAccountOutput represents output from updating an account
type UpdateAccountOutput struct {
	Account *entities.Account
}

// UpdateAccountPort defines the input port for updating accounts
type UpdateAccountPort interface {
	Execute(ctx context.Context, input UpdateAccountInput) (*UpdateAccountOutput, error)
}

// DeactivateShareInput represents input for deactivating a share
type DeactivateShareInput struct {
	AccountID value_objects.AccountID
	ShareID   string
}

// DeactivateSharePort defines the input port for deactivating shares
type DeactivateSharePort interface {
	Execute(ctx context.Context, input DeactivateShareInput) error
}
