package ably

import (
	"context"
	"log"
	"os"
	"sync"

	"github.com/ably/ably-go/ably"
)

var (
	once       sync.Once
	ablyClient *AblyClient
)

type AblyClientInterface interface {
	GetChannel(name string) AblyChannelInterface
}

type AblyChannelInterface interface {
	SubscribeAll(ctx context.Context, handler func(msg *ably.Message)) (func(), error)
	Publish(ctx context.Context, name string, data string) error
}

type AblyClient struct {
	client *ably.Realtime
}

func GetAblyClient() *AblyClient {
	once.Do(func() {
		apiKey := os.Getenv("ABLY_API_KEY")
		client, err := newAblyClient(apiKey)
		if err != nil {
			log.Fatalf("Failed to create Ably client: %v", err)
		}
		ablyClient = client
	})
	return ablyClient
}

func newAblyClient(apiKey string) (*AblyClient, error) {
	client, err := ably.NewRealtime(ably.WithKey(apiKey))
	if err != nil {
		return nil, err
	}
	return &AblyClient{client: client}, nil
}

func (a *AblyClient) GetChannel(name string) AblyChannelInterface {
	return &AblyChannel{channel: a.client.Channels.Get(name)}
}

type AblyChannel struct {
	channel *ably.RealtimeChannel
}

func (c *AblyChannel) SubscribeAll(ctx context.Context, handler func(msg *ably.Message)) (func(), error) {
	return c.channel.SubscribeAll(ctx, handler)
}

func (c *AblyChannel) Publish(ctx context.Context, name string, data string) error {
	return c.channel.Publish(ctx, name, data)
}
