package tests

import (
	"bytes"
	"context"
	"io"
	"strings"
	"sync"
	"sync/atomic"

	"github.com/navidrome/navidrome/core/ffmpeg"
)

func NewMockFFmpeg(data string) *MockFFmpeg {
	return &MockFFmpeg{Reader: strings.NewReader(data), ProbeAvailable: true}
}

type MockFFmpeg struct {
	io.Reader
	lock             sync.Mutex
	closed           atomic.Bool
	Error            error
	ProbeAudioResult *ffmpeg.AudioProbeResult
	ProbeAvailable   bool
}

func (ff *MockFFmpeg) IsAvailable() bool {
	return true
}

func (ff *MockFFmpeg) IsProbeAvailable() bool {
	return ff.ProbeAvailable
}

func (ff *MockFFmpeg) Transcode(_ context.Context, _ ffmpeg.TranscodeOptions) (io.ReadCloser, error) {
	if ff.Error != nil {
		return nil, ff.Error
	}
	return ff, nil
}

func (ff *MockFFmpeg) ExtractImage(context.Context, string) (io.ReadCloser, error) {
	if ff.Error != nil {
		return nil, ff.Error
	}
	return ff, nil
}

func (ff *MockFFmpeg) ConvertAnimatedImage(_ context.Context, reader io.Reader, _ int, _ int) (io.ReadCloser, error) {
	if ff.Error != nil {
		return nil, ff.Error
	}
	data, err := io.ReadAll(reader)
	if err != nil {
		return nil, err
	}
	return io.NopCloser(bytes.NewReader(data)), nil
}

func (ff *MockFFmpeg) Probe(context.Context, []string) (string, error) {
	if ff.Error != nil {
		return "", ff.Error
	}
	return "", nil
}
func (ff *MockFFmpeg) ProbeAudioStream(context.Context, string) (*ffmpeg.AudioProbeResult, error) {
	if ff.Error != nil {
		return nil, ff.Error
	}
	return ff.ProbeAudioResult, nil
}

func (ff *MockFFmpeg) CmdPath() (string, error) {
	if ff.Error != nil {
		return "", ff.Error
	}
	return "ffmpeg", nil
}

func (ff *MockFFmpeg) Version() string {
	return "1.0"
}

func (ff *MockFFmpeg) Read(p []byte) (n int, err error) {
	ff.lock.Lock()
	defer ff.lock.Unlock()
	return ff.Reader.Read(p)
}

func (ff *MockFFmpeg) Close() error {
	ff.closed.Store(true)
	return nil
}

func (ff *MockFFmpeg) IsClosed() bool {
	return ff.closed.Load()
}
