package ytdlp

import (
	"context"
	"encoding/json"
	"fmt"
	"path"
	"sync"

	"git.kmsign.ru/royalcat/tstor/server/pkg/ctxbilly"
	"git.kmsign.ru/royalcat/tstor/server/pkg/ytdlp"
	"git.kmsign.ru/royalcat/tstor/server/src/vfs"
	"github.com/go-git/go-billy/v5/osfs"
	"github.com/royalcat/ctxio"
)

func NewService(dataDir string) (*Daemon, error) {
	client, err := ytdlp.New()
	if err != nil {
		return nil, err
	}

	s := &Daemon{
		mu:          sync.Mutex{},
		client:      client,
		dataDir:     dataDir,
		controllers: make(map[string]*Controller, 0),
	}

	return s, nil
}

type Daemon struct {
	mu sync.Mutex

	dataDir     string
	client      *ytdlp.Client
	controllers map[string]*Controller
}

func (c *Daemon) addSource(s Source) {
	c.mu.Lock()
	defer c.mu.Unlock()

	ctl := newYtdlpController(ctxbilly.WrapFileSystem(osfs.New(c.sourceDir(s))), s, c.client)

	c.controllers[s.Name()] = ctl
}

func (c *Daemon) sourceDir(s Source) string {
	return path.Join(c.dataDir, s.Name())
}

func (c *Daemon) BuildFS(ctx context.Context, sourcePath string, f vfs.File) (vfs.Filesystem, error) {
	data, err := ctxio.ReadAll(ctx, f)
	if err != nil {
		return nil, fmt.Errorf("failed to read source file: %w", err)
	}

	var s Source
	err = json.Unmarshal(data, &s)
	if err != nil {
		return nil, err
	}

	c.addSource(s)

	downloadFS := ctxbilly.WrapFileSystem(osfs.New(c.sourceDir(s)))

	return newSourceFS(path.Base(f.Name()), downloadFS, c, s), nil
}