package grpc

import (
	"context"

	"github.com/sorti/openspeak/internal/auth"
	pb "github.com/sorti/openspeak/pkg/api/openspeak/v1"
)

// AuthServiceServer implements the AuthService gRPC service
type AuthServiceServer struct {
	pb.UnimplementedAuthServiceServer
	server *Server
}

// NewAuthServiceServer creates a new AuthServiceServer
func NewAuthServiceServer(s *Server) *AuthServiceServer {
	return &AuthServiceServer{
		server: s,
	}
}

// Login authenticates a user with a token
func (a *AuthServiceServer) Login(ctx context.Context, req *pb.LoginRequest) (*pb.LoginResponse, error) {
	if req.Token == "" {
		return nil, ErrInvalidToken
	}

	tokenInfo, err := a.server.tokenManager.ValidateToken(req.Token)
	if err != nil {
		return nil, ErrInvalidToken
	}

	permissions := convertPermissionsFromTokenInfo(tokenInfo)

	return &pb.LoginResponse{
		Status:      &pb.Status{Success: true},
		UserId:      tokenInfo.UserID,
		Permissions: permissions,
	}, nil
}

// ValidateToken validates a given token
func (a *AuthServiceServer) ValidateToken(ctx context.Context, req *pb.ValidateTokenRequest) (*pb.ValidateTokenResponse, error) {
	if req.Token == "" {
		return nil, ErrInvalidToken
	}

	tokenInfo, err := a.server.tokenManager.ValidateToken(req.Token)
	if err != nil {
		return &pb.ValidateTokenResponse{
			Valid: false,
		}, nil
	}

	permissions := convertPermissionsFromTokenInfo(tokenInfo)

	return &pb.ValidateTokenResponse{
		Valid:       true,
		UserId:      tokenInfo.UserID,
		Permissions: permissions,
	}, nil
}

// GetMyPermissions returns the permissions of the authenticated user
func (a *AuthServiceServer) GetMyPermissions(ctx context.Context, req *pb.GetMyPermissionsRequest) (*pb.GetMyPermissionsResponse, error) {
	// Extract token from context
	token, ok := ctx.Value("token").(string)
	if !ok || token == "" {
		return nil, ErrUnauthorized
	}

	tokenInfo, err := a.server.tokenManager.ValidateToken(token)
	if err != nil {
		return nil, ErrUnauthorized
	}

	permissions := convertPermissionsFromTokenInfo(tokenInfo)

	return &pb.GetMyPermissionsResponse{
		UserId:      tokenInfo.UserID,
		Permissions: permissions,
	}, nil
}

// convertPermissionsFromTokenInfo returns permissions from token info
func convertPermissionsFromTokenInfo(tokenInfo *auth.TokenInfo) []string {
	return tokenInfo.Permissions
}
