package ffmpeg

import (
	"fmt"
	"github.com/tcolgate/mp3"
	"github.com/youpy/go-wav"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"
)

// 音频转码配置
type TranscodeConfig struct {
	InputPath  string // 输入文件路径（MP3/WAV）
	OutputPath string // 输出文件路径（G711A）
	SampleRate int    // 采样率（默认 8000 Hz，G711A 标准采样率）
	Channels   int    // 声道数（默认 1，单声道）
}

// 默认转码配置
func defaultTranscodeConfig(input, output string) TranscodeConfig {
	return TranscodeConfig{
		InputPath:  input,
		OutputPath: output,
		SampleRate: 8000, // G711A 标准采样率
		Channels:   1,    // 单声道（电话/语音常用）
	}
}

// 校验输入文件类型（仅允许 MP3/WAV）
func validateInputFile(inputPath string) error {
	// 检查文件是否存在
	if _, err := os.Stat(inputPath); os.IsNotExist(err) {
		return fmt.Errorf("输入文件不存在: %s", inputPath)
	}

	// 校验文件扩展名
	ext := strings.ToLower(filepath.Ext(inputPath))
	if ext != ".mp3" && ext != ".wav" {
		return fmt.Errorf("仅支持 MP3/WAV 格式，当前文件扩展名: %s", ext)
	}

	return nil
}

// MP3/WAV 转 G711A（PCMA）
func TranscodeToG711A(config TranscodeConfig) error {
	// 1. 校验输入文件
	if err := validateInputFile(config.InputPath); err != nil {
		return err
	}

	// 2. 补全默认配置
	if config.SampleRate <= 0 {
		config.SampleRate = 8000
	}
	if config.Channels <= 0 {
		config.Channels = 1
	}

	// 3. 确保输出目录存在
	outputDir := filepath.Dir(config.OutputPath)
	if err := os.MkdirAll(outputDir, 0755); err != nil {
		return fmt.Errorf("创建输出目录失败: %v", err)
	}

	// 4. 构建 FFmpeg 命令
	// 核心参数说明：
	// -i: 输入文件
	// -ar: 采样率
	// -ac: 声道数
	// -f: 输出格式（alaw 即 G711A）
	// -y: 覆盖已存在的输出文件
	cmdArgs := []string{
		"-i", config.InputPath,
		"-ar", fmt.Sprintf("%d", config.SampleRate),
		"-ac", fmt.Sprintf("%d", config.Channels),
		"-f", "alaw", // 指定输出格式为 G711A（PCMA）
		"-y", // 覆盖输出文件（无需确认）
		config.OutputPath,
	}
	dir, _ := os.Getwd() // Windows 路径用反斜杠，或双正斜杠
	ffmpegPath := ""
	switch runtime.GOOS {
	case "linux":
		ffmpegPath = filepath.Join(dir, "ffmpeg")
	case "windows":
		ffmpegPath = filepath.Join(dir, "ffmpeg.exe")
	}

	// 执行 FFmpeg 命令
	cmd := exec.Command(ffmpegPath, cmdArgs...)
	// 捕获 FFmpeg 输出（便于调试）
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("转码失败: %v, FFmpeg 输出: %s", err, string(output))
	}

	// 校验输出文件是否生成
	if _, err := os.Stat(config.OutputPath); os.IsNotExist(err) {
		return fmt.Errorf("转码后输出文件未生成: %s", config.OutputPath)
	}

	fmt.Printf("转码成功！输入: %s → 输出: %s\n", config.InputPath, config.OutputPath)
	return nil
}
func TranscodeToG711AFile(inputFile, outputFile string) error {
	// 也可自定义配置（比如调整采样率）
	/*
		customConfig := TranscodeConfig{
			InputPath:  "./uploads/test.wav",
			OutputPath: "./uploads/test_custom.g711a",
			SampleRate: 16000, // 自定义采样率
			Channels:   1,
		}
		err = TranscodeToG711A(customConfig)
	*/
	// 使用默认配置转码
	err := TranscodeToG711A(defaultTranscodeConfig(inputFile, outputFile))
	if err != nil {
		fmt.Printf("转码失败: %v\n", err)
		return fmt.Errorf("转码失败: %v\n", err)
	}
	return nil

}

// GetMP3Duration 获取MP3文件时长
func GetMP3Duration(filePath string) (time.Duration, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return 0, err
	}
	defer file.Close()

	decoder := mp3.NewDecoder(file)
	var frame mp3.Frame
	var totalDuration float64
	skipped := 0

	for {
		if err := decoder.Decode(&frame, &skipped); err != nil {
			if err == io.EOF {
				break
			}
			return 0, err
		}
		totalDuration += frame.Duration().Seconds()
	}

	duration := time.Duration(totalDuration * float64(time.Second))
	return duration, nil
}

// GetWAVDurationOptimized 优化的WAV文件时长获取方法
func GetWAVDurationOptimized(filePath string) (time.Duration, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return 0, err
	}
	defer file.Close()

	reader := wav.NewReader(file)

	// 使用库提供的Duration方法
	duration, err := reader.Duration()
	if err != nil {
		return 0, err
	}

	return duration, nil
}

// GetAudioDuration 获取音频文件时长（支持MP3和WAV）
func GetAudioDuration(filePath string) (time.Duration, string, error) {
	// 根据文件扩展名判断文件类型
	if len(filePath) > 4 {
		ext := filePath[len(filePath)-4:]
		switch ext {
		case ".mp3":
			duration, err := GetMP3Duration(filePath)
			return duration, "MP3", err
		case ".wav":
			duration, err := GetWAVDurationOptimized(filePath)
			return duration, "WAV", err
		default:
			return 0, "", fmt.Errorf("不支持的音频格式: %s", ext)
		}
	}

	// 如果无法从扩展名判断，可以尝试根据文件头部信息判断
	return 0, "", fmt.Errorf("无法识别的音频格式")
}
