package ffmpeg

import (
	"context"
	"encoding/json"
	"fmt"
	"os"
	"os/exec"
	"strconv"

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

const ffprobeExecutable = "ffprobe"

type FfmpegMetaViewer struct {
}

// ffprobeOutput представляет структуру JSON-ответа от ffprobe
type ffprobeOutput struct {
	Format struct {
		Duration string `json:"duration"`
	} `json:"format"`
}

func NewFfmpegMetaViewer() *FfmpegMetaViewer {
	return &FfmpegMetaViewer{}
}

func (m *FfmpegMetaViewer) GetInfo(ctx context.Context, src string) (*contract.AudioInfo, error) {
	// Проверяем существование исходного файла
	if _, err := os.Stat(src); os.IsNotExist(err) {
		return nil, fmt.Errorf("input file does not exist: %s", src)
	}

	// Проверяем, что ffprobe доступен в системе
	if _, err := exec.LookPath(ffprobeExecutable); err != nil {
		return nil, fmt.Errorf("ffprobe not found in PATH: %w", err)
	}

	// Команда заводится с контекстом: отправитель, закрывший соединение, не
	// оставляет за собой чтение метаданных чужого файла.
	cmd := exec.CommandContext(ctx, ffprobeExecutable,
		"-v", "quiet", // тихий режим (без лишнего вывода)
		"-print_format", "json", // вывод в формате JSON
		"-show_format", // показать информацию о формате
		src,            // входной файл
	)

	// Выполняем команду и получаем вывод
	output, err := cmd.Output()
	if err != nil {
		return nil, fmt.Errorf("ffprobe execution failed: %w", err)
	}

	// Парсим JSON-ответ
	var probeResult ffprobeOutput
	if err := json.Unmarshal(output, &probeResult); err != nil {
		return nil, fmt.Errorf("failed to parse ffprobe output: %w", err)
	}

	// Конвертируем длительность из строки в секунды
	durationFloat, err := strconv.ParseFloat(probeResult.Format.Duration, 64)
	if err != nil {
		return nil, fmt.Errorf("failed to parse duration: %w", err)
	}

	// Округляем до целых секунд
	durationSeconds := int(durationFloat + 0.5) // +0.5 для правильного округления

	return &contract.AudioInfo{
		Seconds: durationSeconds,
	}, nil
}
