package plugin_test

import (
	"errors"
	"fmt"
	"net/http"
	"os/exec"
	"strings"

	task "github.com/langhuihui/gotask"
)

func init() {
	testTaskFactory.Register("push", func(s *TestCase, conf TestTaskConfig) task.ITask {
		return &AcceptPushTask{TestBaseTask: TestBaseTask{testCase: s, TestTaskConfig: conf}}
	})
}

// AcceptPushTask RTSP 推流任务
type AcceptPushTask struct {
	TestBaseTask
}

// Start 任务开始
func (rt *AcceptPushTask) Start() error {
	if rt.Input == "" {
		rt.Input = "test.mp4"
	}
	// 构建 FFmpeg 命令
	args := []string{
		"-hide_banner",
		"-re", // 以实时速率读取输入
		"-stream_loop", "-1", "-i", rt.Input,
	}
	// 添加视频编码参数
	if !rt.testCase.AudioOnly {
		args = append(args, "-c:v", rt.testCase.VideoCodec, "-b:v", "200k")
	} else {
		args = append(args, "-vn")
	}

	// 添加音频编码参数
	if !rt.testCase.VideoOnly {
		args = append(args, "-c:a", rt.testCase.AudioCodec)
	} else {
		args = append(args, "-an")
	}

	switch rt.Format {
	case "rtsp":
		args = append(args,
			"-f", "rtsp",
			"-rtsp_transport", "tcp",
			fmt.Sprintf("rtsp://%s/%s", rt.ServerAddr, rt.StreamPath),
		)
	case "rtmp":
		args = append(args,
			"-f", "flv",
			fmt.Sprintf("rtmp://%s/%s", rt.ServerAddr, rt.StreamPath),
		)
	case "srt":
		args = append(args, "-f", "mpegts", fmt.Sprintf("srt://%s?streamid=publish:/%s", rt.ServerAddr, rt.StreamPath))
	case "webrtc":
		args = append(args, "-f", "whip", fmt.Sprintf("http://%s:8080/webrtc/push/%s", rt.ServerAddr, rt.StreamPath))
	case "ps":
		host := rt.ServerAddr
		if !strings.Contains(host, ":") {
			host += ":8080"
		}
		body := strings.NewReader(`{"streamPath":"` + rt.StreamPath + `","port":50000}`)
		req, err := http.NewRequestWithContext(rt, "POST", "http://"+host+"/rtp/receive/ps", body)
		if err != nil {
			return err
		}
		req.Header.Set("Content-Type", "application/json")
		go func() {
			res, err := http.DefaultClient.Do(req)
			if err != nil {
				rt.Stop(err)
				return
			}
			rt.Info(res.Status, "code", res.StatusCode, "url", req.URL)
			if res.StatusCode != http.StatusOK {
				rt.Stop(errors.New("receive ps failed"))
				return
			}
			defer res.Body.Close()
		}()
	}

	rt.Info("FFmpeg command", "command", strings.Join(args, " "))

	// 创建进程
	cmd := exec.Command("ffmpeg", args...)
	// 日志重定向
	cmd.Stdout = rt.testCase
	cmd.Stderr = rt.testCase
	// 启动进程
	if err := cmd.Start(); err != nil {
		rt.testCase.Status = TestCaseStatusFailed
		return err
	}
	rt.OnStop(cmd.Process.Kill)
	return nil
}
