package livekit

import (
	"context"
	"time"

	"github.com/flowy-live/llink/internal/utils"
	"github.com/livekit/protocol/auth"
	"github.com/livekit/protocol/livekit"
	lksdk "github.com/livekit/server-sdk-go/v2"
)

type Client interface {
	// GetJoinToken mints a participant JWT; name surfaces as the display name.
	GetJoinToken(roomId string, humanId string, name string) (string, error)
	ServerUrl() string
	ListParticipants(ctx context.Context, roomName string) ([]*livekit.ParticipantInfo, error)
	// KeyProvider is used by handlers to verify webhook signatures.
	KeyProvider() auth.KeyProvider
}

type clientImpl struct {
	apiSecret   string
	apiKey      string
	hostUrl     string
	roomService *lksdk.RoomServiceClient
	keyProvider auth.KeyProvider
}

func NewClient() Client {
	apiKey := utils.MustGetEnv("LIVEKIT_API_KEY")
	apiSecret := utils.MustGetEnv("LIVEKIT_API_SECRET")
	hostUrl := utils.MustGetEnv("LIVEKIT_URL")

	roomService := lksdk.NewRoomServiceClient(hostUrl, apiKey, apiSecret)

	return &clientImpl{
		apiSecret:   apiSecret,
		apiKey:      apiKey,
		hostUrl:     hostUrl,
		roomService: roomService,
		keyProvider: auth.NewSimpleKeyProvider(apiKey, apiSecret),
	}
}

func (c *clientImpl) ServerUrl() string {
	return c.hostUrl
}

func (c *clientImpl) GetJoinToken(room, humanId, name string) (string, error) {
	at := auth.NewAccessToken(c.apiKey, c.apiSecret)
	grant := &auth.VideoGrant{
		RoomJoin: true,
		Room:     room,
	}
	at.SetVideoGrant(grant).
		SetIdentity(humanId).
		SetName(name).
		SetValidFor(time.Hour)

	return at.ToJWT()
}

func (c *clientImpl) ListParticipants(ctx context.Context, roomName string) ([]*livekit.ParticipantInfo, error) {
	resp, err := c.roomService.ListParticipants(ctx, &livekit.ListParticipantsRequest{
		Room: roomName,
	})
	if err != nil {
		return nil, err
	}
	return resp.Participants, nil
}

func (c *clientImpl) KeyProvider() auth.KeyProvider {
	return c.keyProvider
}
