package recognizer

import (
	"context"
	"encoding/json"
	"errors"
	"io"

	"github.com/google/uuid"

	"git.vakhrushev.me/av/transcriber/internal/entity"
)

// MemoryAudioRecognizer — подставной распознаватель для местного запуска и
// проверок. Прогон на реальных ключах ради проверки кода запрещён: распознавание
// и хранение в Object Storage оплачиваются по факту.
//
// Сырой ответ он отдаёт своего вида, но настоящего: тем же путём, что и живой
// адаптер, — сохранённые байты разбираются обратно в реплики, и структура
// строится без единого обращения наружу.
type MemoryAudioRecognizer struct{}

const memoryProvider = "memory"

func (r *MemoryAudioRecognizer) Provider() string { return memoryProvider }

func (r *MemoryAudioRecognizer) Model() string { return "memory" }

func (r *MemoryAudioRecognizer) Upload(ctx context.Context, file io.Reader, objectKey string) (string, error) {
	return "memory://" + objectKey, nil
}

func (r *MemoryAudioRecognizer) ObjectExists(ctx context.Context, objectKey string, size int64) (bool, error) {
	return false, nil
}

func (r *MemoryAudioRecognizer) Submit(ctx context.Context, sourceURI string) (string, error) {
	return uuid.NewString(), nil
}

func (r *MemoryAudioRecognizer) CheckStatus(ctx context.Context, operationID string) (*entity.RecognitionResult, error) {
	return entity.NewCompletedResult(), nil
}

func (r *MemoryAudioRecognizer) Fetch(ctx context.Context, operationID string) (*entity.RecognitionOutcome, error) {
	replicas := []entity.Replica{
		{StartMs: 0, EndMs: 1000, Text: "Foo bar,"},
		{StartMs: 1000, EndMs: 2000, Text: "Baz."},
	}
	raw, err := json.Marshal(replicas)
	if err != nil {
		return nil, errors.New("failed to encode memory payload")
	}
	return &entity.RecognitionOutcome{
		Replicas:  replicas,
		PlainText: "Foo bar, Baz.",
		Raw:       raw,
	}, nil
}

func (r *MemoryAudioRecognizer) Parse(raw []byte) (*entity.RecognitionOutcome, error) {
	var replicas []entity.Replica
	if err := json.Unmarshal(raw, &replicas); err != nil {
		return nil, errors.New("failed to decode memory payload")
	}

	var plain []byte
	for _, replica := range replicas {
		if len(plain) > 0 {
			plain = append(plain, ' ')
		}
		plain = append(plain, replica.Text...)
	}

	return &entity.RecognitionOutcome{
		Replicas:  replicas,
		PlainText: string(plain),
		Raw:       raw,
	}, nil
}
