package input

import (
	"context"
	"time"

	"github.com/google/uuid"
	"github.com/rwadurian/mpc-system/services/session-coordinator/application/ports/output"
	"github.com/rwadurian/mpc-system/services/session-coordinator/domain/entities"
)

// SessionManagementPort defines the input port for session management
// This is the interface that use cases implement
type SessionManagementPort interface {
	// CreateSession creates a new MPC session
	CreateSession(ctx context.Context, input CreateSessionInput) (*CreateSessionOutput, error)

	// JoinSession allows a participant to join a session
	JoinSession(ctx context.Context, input JoinSessionInput) (*JoinSessionOutput, error)

	// GetSessionStatus retrieves the status of a session
	GetSessionStatus(ctx context.Context, sessionID uuid.UUID) (*SessionStatusOutput, error)

	// ReportCompletion reports that a participant has completed
	ReportCompletion(ctx context.Context, input ReportCompletionInput) (*ReportCompletionOutput, error)

	// CloseSession closes a session
	CloseSession(ctx context.Context, sessionID uuid.UUID) error
}

// PartyComposition defines the composition of parties required for a session
type PartyComposition struct {
	PersistentCount int                // Number of persistent parties (store shares in database)
	DelegateCount   int                // Number of delegate parties (generate and return shares)
	TemporaryCount  int                // Number of temporary parties
	CustomFilters   []output.PartySelectionFilter // Custom party selection filters
}

// DelegateUserShare contains user's share for delegate party to use in signing
type DelegateUserShare struct {
	DelegatePartyID string // The delegate party that will use this share
	EncryptedShare  []byte // User's encrypted share
	PartyIndex      int32  // Party index for this share
}

// CreateSessionInput contains input for creating a session
type CreateSessionInput struct {
	InitiatorID       string
	SessionType       string // "keygen" or "sign"
	ThresholdN        int
	ThresholdT        int
	Participants      []ParticipantInfo
	PartyComposition  *PartyComposition  // Optional: specify party composition by role
	MessageHash       []byte             // For sign sessions
	ExpiresIn         time.Duration
	DelegateUserShare *DelegateUserShare // For sign sessions with delegate party
	KeygenSessionID   uuid.UUID          // For sign sessions: which keygen session's shares to use
	WalletName        string             // For co_managed_keygen: wallet name
	InviteCode        string             // For co_managed_keygen: invite code for participants
}

// ParticipantInfo contains information about a participant
type ParticipantInfo struct {
	PartyID    string
	DeviceInfo entities.DeviceInfo
	PartyIndex int // Original party index from keygen (required for signing)
}

// CreateSessionOutput contains output from creating a session
type CreateSessionOutput struct {
	SessionID  uuid.UUID
	JoinTokens map[string]string // PartyID -> JoinToken
	ExpiresAt  time.Time
}

// JoinSessionInput contains input for joining a session
type JoinSessionInput struct {
	SessionID  uuid.UUID
	PartyID    string
	JoinToken  string
	DeviceInfo entities.DeviceInfo
}

// JoinSessionOutput contains output from joining a session
type JoinSessionOutput struct {
	Success      bool
	PartyIndex   int
	SessionInfo  SessionInfo
	OtherParties []PartyInfo
}

// SessionInfo contains session information
type SessionInfo struct {
	SessionID       uuid.UUID
	SessionType     string
	ThresholdN      int
	ThresholdT      int
	MessageHash     []byte
	Status          string
	KeygenSessionID uuid.UUID // For sign sessions: which keygen session's shares to use
}

// PartyInfo contains party information
type PartyInfo struct {
	PartyID    string
	PartyIndex int
	DeviceInfo entities.DeviceInfo
}

// SessionStatusOutput contains session status information
type SessionStatusOutput struct {
	SessionID       uuid.UUID
	Status          string
	SessionType     string // "keygen" or "sign"
	ThresholdT      int
	ThresholdN      int
	Participants    []ParticipantStatus
	PublicKey       []byte // For completed keygen
	Signature       []byte // For completed sign
	HasDelegate     bool   // True if keygen session has a delegate party (always false for sign)
	DelegatePartyID string // The delegate party ID (if any, only for keygen)
}

// ParticipantStatus contains participant status information
type ParticipantStatus struct {
	PartyID    string
	PartyIndex int
	Status     string
}

// ReportCompletionInput contains input for reporting completion
type ReportCompletionInput struct {
	SessionID uuid.UUID
	PartyID   string
	PublicKey []byte // For keygen
	Signature []byte // For sign
}

// ReportCompletionOutput contains output from reporting completion
type ReportCompletionOutput struct {
	Success      bool
	AllCompleted bool
}
