package contract

import (
	"context"
	"io"

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

type AudioInfo struct {
	Seconds int // Длина аудиофайла в секундах
}

// Контекст первым доводом несут все интерфейсы, за которыми стоит внешний
// собеседник — процесс `ffmpeg`, S3, SpeechKit. Он здесь не украшение: остановка
// сервиса обязана доходить до чужой работы, а не оставлять её сиротой. Без него
// конвертация шестичасовой записи переживает остановку воркера, а запрос к
// платному распознаванию висит до собственного таймаута библиотеки.
type AudioMetaViewer interface {
	GetInfo(ctx context.Context, src string) (*AudioInfo, error)
}

type AudioFileConverter interface {
	Convert(ctx context.Context, src, dest string) error
}

// AudioRecognizer — внешний распознаватель речи.
//
// Заливка и отправка операции разделены: это два обращения с разной ценой
// повтора. Повтор заливки бесплатен и кладёт объект под тем же ключом; повтор
// отправки оплачивается наружу, и шаг обязан проверить сделанное прежде, чем
// платить второй раз.
//
// Результат отдаётся **доменным** — реплики со временем, плоский текст и байты
// ответа на хранение, — а не сырым форматом провайдера: разбор потока это
// обязанность адаптера, и ни один шаг конвейера не знает, каким потоком и какими
// полями провайдер отвечает.
type AudioRecognizer interface {
	// Provider — имя провайдера, под которым сохраняется попытка.
	Provider() string
	// Model — имя модели распознавания.
	Model() string
	// Upload кладёт аудио туда, откуда провайдер его прочитает, и отдаёт адрес.
	// Повтор кладёт объект под тем же ключом и оплаты не стоит.
	Upload(ctx context.Context, file io.Reader, objectKey string) (sourceURI string, err error)
	// ObjectExists отвечает, лежит ли объект нужного размера. По нему шаг решает,
	// повторять ли заливку; сверка содержимого хешем ненадёжна — признак
	// целостности у составного объекта не равен отпечатку содержимого.
	ObjectExists(ctx context.Context, objectKey string, size int64) (bool, error)
	// Submit заводит операцию распознавания по адресу аудио. Оплачивается
	// наружу.
	Submit(ctx context.Context, sourceURI string) (operationID string, err error)
	// CheckStatus опрашивает операцию.
	CheckStatus(ctx context.Context, operationID string) (*entity.RecognitionResult, error)
	// Fetch забирает готовый результат и отдаёт его доменным.
	Fetch(ctx context.Context, operationID string) (*entity.RecognitionOutcome, error)
	// Parse строит доменный результат из **сохранённого** ответа провайдера, не
	// обращаясь к нему. По нему архив пересчитывается без единого рубля.
	Parse(raw []byte) (*entity.RecognitionOutcome, error)
}
