package use_cases

import (
	"context"

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

// GetSessionStatusUseCase implements the get session status use case
type GetSessionStatusUseCase struct {
	sessionRepo repositories.SessionRepository
}

// NewGetSessionStatusUseCase creates a new get session status use case
func NewGetSessionStatusUseCase(
	sessionRepo repositories.SessionRepository,
) *GetSessionStatusUseCase {
	return &GetSessionStatusUseCase{
		sessionRepo: sessionRepo,
	}
}

// Execute executes the get session status use case
func (uc *GetSessionStatusUseCase) Execute(
	ctx context.Context,
	sessionID uuid.UUID,
) (*input.SessionStatusOutput, error) {
	// 1. Load session
	sessionIDVO := value_objects.SessionIDFromUUID(sessionID)
	session, err := uc.sessionRepo.FindByID(ctx, sessionIDVO)
	if err != nil {
		return nil, err
	}

	// 2. Build participants list
	participants := make([]input.ParticipantStatus, len(session.Participants))
	for i, p := range session.Participants {
		participants[i] = input.ParticipantStatus{
			PartyID:    p.PartyID.String(),
			PartyIndex: p.PartyIndex,
			Status:     p.Status.String(),
		}
	}

	// 3. For completed sign sessions, get signature from cache
	var signature []byte
	if session.SessionType == entities.SessionTypeSign && session.Status.String() == "completed" {
		signature, _ = memory.GetSignatureCache().Get(sessionID)
	}

	// 4. Build response
	// has_delegate is only meaningful for keygen sessions
	hasDelegate := session.DelegatePartyID != "" && string(session.SessionType) == "keygen"
	return &input.SessionStatusOutput{
		SessionID:       session.ID.UUID(),
		Status:          session.Status.String(),
		SessionType:     string(session.SessionType),
		ThresholdT:      session.Threshold.T(),
		ThresholdN:      session.Threshold.N(),
		Participants:    participants,
		PublicKey:       session.PublicKey,
		Signature:       signature,
		HasDelegate:     hasDelegate,
		DelegatePartyID: session.DelegatePartyID,
	}, nil
}
