package api

import (
	"easyaudioencode/internal/core/audioencode"
	"easyaudioencode/pkg/ffmpeg"
	"fmt"
	"git.lnton.com/lnton/pkg/reason"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

// 配置常量
const (
	// 最大上传文件大小 100MB
	maxUploadSize = 100 * 1024 * 1024
	// 文件保存目录
	uploadDir = "./uploads"
	sourceDir = "source"
	encodeDir = "encode"
)

var (
	// 允许的文件扩展名
	allowedExts = map[string]bool{
		".mp3": true,
		".wav": true,
	}
	// 允许的 MIME 类型
	allowedMimeTypes = map[string]bool{
		"audio/mpeg":     true, // MP3
		"audio/wav":      true, // WAV
		"audio/x-wav":    true, // WAV 另一种常见 MIME
		"audio/x-pn-wav": true,
	}
)

// uploadAudioHandler 处理音频文件上传
func (a AudioEncodeAPI) uploadAudioHandler(c *gin.Context, _ *struct{}) (any, error) {
	if err := os.MkdirAll(filepath.Join(uploadDir, sourceDir), 0755); err != nil {
		return nil, reason.ErrServer.SetMsg(fmt.Sprintf("创建上传目录失败: %v", err.Error()))
	}
	if err := os.MkdirAll(filepath.Join(uploadDir, encodeDir), 0755); err != nil {
		return nil, reason.ErrServer.SetMsg(fmt.Sprintf("创建转码目录失败: %v", err.Error()))
	}
	// 限制请求体大小
	c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, maxUploadSize)
	if err := c.Request.ParseMultipartForm(maxUploadSize); err != nil {
		return nil, reason.ErrServer.SetMsg(fmt.Sprintf("文件过大（最大 %dMB）或解析失败: %v", maxUploadSize/1024/1024, err))
	}

	// 获取上传的文件
	file, fileHeader, err := c.Request.FormFile("audio")
	if err != nil {
		return nil, reason.ErrServer.SetMsg(fmt.Sprintf("获取文件失败: %v", err))
	}
	defer file.Close()

	// 1. 校验文件扩展名
	fileExt := strings.ToLower(filepath.Ext(fileHeader.Filename))
	sourceFileName := strings.TrimSuffix(fileHeader.Filename, fileExt)
	if !allowedExts[fileExt] {
		return nil, reason.ErrServer.SetMsg(fmt.Sprintf("不支持的文件类型，仅允许 MP3/WAV，当前扩展名: %s", fileExt))
	}

	// 2. 校验文件 MIME 类型
	//mimeType, err := getFileMimeType(file)
	//if err != nil {
	//	return nil, reason.ErrServer.SetMsg(fmt.Sprintf("获取文件 MIME 类型失败: %v", err))
	//}
	//if !allowedMimeTypes[mimeType] {
	//	return nil, reason.ErrServer.SetMsg(fmt.Sprintf("文件类型校验失败，实际 MIME: %s，仅允许 MP3/WAV", mimeType))
	//}
	uuidStr := uuid.New().String()
	// 生成唯一文件名（避免覆盖）
	fileName := fmt.Sprintf("%s%s", uuidStr, fileExt)
	filePath := filepath.Join(uploadDir, sourceDir, fileName)
	outputFile := filepath.Join(uploadDir, encodeDir, fmt.Sprintf("%s.g711a", uuidStr))
	// 创建目标文件
	dstFile, err := os.Create(filePath)
	if err != nil {
		return nil, reason.ErrServer.SetMsg(fmt.Sprintf("创建文件失败: %v", err))
	}
	defer dstFile.Close()

	// 复制文件内容
	if _, err := io.Copy(dstFile, file); err != nil {
		return nil, reason.ErrServer.SetMsg(fmt.Sprintf("保存文件失败: %v", err.Error()))
	}

	in := &audioencode.AddAudioEncodeInput{
		Name:         sourceFileName,
		FileName:     fileName,
		Size:         fileHeader.Size,
		SourceUrl:    filePath,
		EncodeUrl:    outputFile,
		Mode:         fileExt,
		EncodeStatus: audioencode.EncodeStatusPing,
	}
	duration, _, err := ffmpeg.GetAudioDuration(filePath)
	if err == nil {
		in.Duration = int64(duration.Seconds())
	}
	info, err := a.core.AddAudioEncode(c.Request.Context(), in)
	if err != nil {
		return nil, reason.ErrServer.SetMsg(fmt.Sprintf(`add audioencode err [%s]`, err.Error()))
	}
	a.transcodeCore.StartAudioEncode(filePath, outputFile, info.ID)
	return gin.H{"data": "上传成功!", "filePath": filePath, "filename": fileName, "size": fileHeader.Size, "ID": info.ID}, err
}

// getFileMimeType 获取文件的真实 MIME 类型（通过读取文件前几个字节）
func getFileMimeType(file multipart.File) (string, error) {
	// 读取文件前 512 字节用于检测 MIME 类型
	buffer := make([]byte, 512)
	n, err := file.Read(buffer)
	if err != nil && err != io.EOF {
		return "", err
	}

	// 重置文件指针到开头
	if _, err := file.Seek(0, io.SeekStart); err != nil {
		return "", err
	}

	// 检测 MIME 类型
	return http.DetectContentType(buffer[:n]), nil
}
