package audio

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
)

// NormalizeFormat 规范化音频格式字符串。
func NormalizeFormat(format string) string {
	switch strings.ToLower(format) {
	case "pcm", "wav", "mp3", "mpeg", "ogg", "opus", "flac", "m4a", "mp4", "aac", "webm", "amr":
		return strings.ToLower(format)
	default:
		return format
	}
}

// ConvertToPCM16 将音频数据转换为 16-bit PCM 16000Hz mono。
// 对于已经是 PCM 的数据直接返回；对于 WAV 跳过 44 字节头部；
// 其他格式使用 ffmpeg 转码。
func ConvertToPCM16(data []byte, format string) ([]byte, error) {
	normFormat := NormalizeFormat(format)
	switch normFormat {
	case "pcm":
		return data, nil
	case "wav":
		if len(data) > 44 {
			return data[44:], nil
		}
		return data, nil
	default:
		return transcodeToPCM(data, normFormat)
	}
}

// transcodeToPCM 使用 ffmpeg 将音频数据转码为 PCM 16-bit 16000Hz mono。
func transcodeToPCM(data []byte, format string) ([]byte, error) {
	inFile, err := os.CreateTemp(os.TempDir(), "cyrene-asr-in-*."+format)
	if err != nil {
		return nil, fmt.Errorf("创建输入临时文件失败: %w", err)
	}
	inPath := inFile.Name()
	defer os.Remove(inPath)
	if _, err := inFile.Write(data); err != nil {
		inFile.Close()
		return nil, fmt.Errorf("写入输入临时文件失败: %w", err)
	}
	inFile.Close()

	outFile, err := os.CreateTemp(os.TempDir(), "cyrene-asr-out-*.pcm")
	if err != nil {
		return nil, fmt.Errorf("创建输出临时文件失败: %w", err)
	}
	outPath := outFile.Name()
	outFile.Close()
	defer os.Remove(outPath)

	cmd := exec.Command("ffmpeg",
		"-i", inPath,
		"-ar", "16000",
		"-ac", "1",
		"-c:a", "pcm_s16le",
		"-f", "s16le",
		outPath,
		"-y",
	)
	cmd.Stderr = nil

	if err := cmd.Run(); err != nil {
		return nil, fmt.Errorf("音频转码失败 (ffmpeg): %w", err)
	}

	outData, err := os.ReadFile(outPath)
	if err != nil {
		return nil, fmt.Errorf("读取转码结果失败: %w", err)
	}

	return outData, nil
}

// IsFFmpegAvailable 检查 ffmpeg 是否可执行。
func IsFFmpegAvailable() bool {
	_, err := exec.LookPath("ffmpeg")
	return err == nil
}
