package services

import (
	"errors"
	"eta/eta_api/models"
	"eta/eta_api/utils"
	"fmt"
	"io"
	"mime/multipart"
	"os"
	"os/exec"
	"time"
)

// UploadToOssAndFileName 上传到oss并使用这个名称
func UploadToOssAndFileName(fileMulti multipart.File, newFileName string) (resourceUrl string, err error) {
	dateDir := time.Now().Format("20060102")
	uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
	err = os.MkdirAll(uploadDir, utils.DIR_MOD)
	if err != nil {
		err = errors.New("存储目录创建失败,Err:" + err.Error())
		return
	}

	//本地地址
	fpath := uploadDir + "/" + newFileName
	err = saveToFile(fileMulti, fpath)
	if err != nil {
		err = errors.New("文件上传失败,Err:" + err.Error())
		return
	}

	//上传到阿里云 和 minio
	//if utils.ObjectStorageClient == "minio" {
	//	resourceUrl, err = UploadImgToMinIo(newFileName, fpath)
	//	if err != nil {
	//		err = errors.New("文件上传失败,Err:" + err.Error())
	//		return
	//	}
	//} else {
	//	resourceUrl, err = UploadAliyunV2(newFileName, fpath)
	//	if err != nil {
	//		err = errors.New("文件上传失败,Err:" + err.Error())
	//		return
	//	}
	//}
	ossClient := NewOssClient()
	if ossClient == nil {
		err = fmt.Errorf("初始化OSS服务失败")
		return
	}
	resourceUrl, err = ossClient.UploadFile(newFileName, fpath, "")
	if err != nil {
		err = fmt.Errorf("文件上传失败, Err: %s", err.Error())
		return
	}

	defer func() {
		os.Remove(fpath)
	}()

	item := new(models.Resource)
	item.ResourceUrl = resourceUrl
	item.ResourceType = 1
	item.CreateTime = time.Now()
	_, err = models.AddResource(item)
	if err != nil {
		err = errors.New("资源上传失败,Err:" + err.Error())
		return
	}
	return
}

// saveToFile 保存到本地文件
func saveToFile(fileMulti multipart.File, tofile string) error {
	f, err := os.OpenFile(tofile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
	if err != nil {
		return err
	}
	defer f.Close()
	io.Copy(f, fileMulti)
	return nil
}

// GetResourceUrlBySvgImg
// @Description: 通过svg图片生成图片资源地址(传到OSS后的地址)
// @author: Roc
// @datetime 2024-07-16 10:18:09
// @param imgData string
// @return resourceUrl string
// @return err error
// @return errMsg string
func GetResourceUrlBySvgImg(imgData string) (resourceUrl string, err error, errMsg string) {
	errMsg = "图表保存失败"
	uploadDir := "static/images/"
	if !utils.FileIsExist(uploadDir) {
		err = os.MkdirAll(uploadDir, utils.DIR_MOD)
		if err != nil {
			err = errors.New("存储目录创建失败,Err:" + err.Error())
			return
		}
	}

	//var saveToOssPath string
	randStr := utils.GetRandStringNoSpecialChar(28)
	var fileName, outFileName string
	fileName = randStr + ".txt"
	fileName = uploadDir + fileName
	err = utils.SaveToFile(imgData, fileName)
	if err != nil {
		err = errors.New("图片保存失败,Err:" + err.Error())
		return
	}

	// 删除临时存储的svg文件
	defer func() {
		err = os.Remove(fileName)
		if err != nil {
			utils.FileLog.Info("删除临时存储的svg文件失败, err: " + err.Error())
		}
	}()
	outFileName = randStr + ".png"

	doneChannel := make(chan bool, 1)
	errorChannel := make(chan error, 1)

	cmd := exec.Command("highcharts-export-server", "--infile", fileName, "--constr", "Chart", "--scale", "2", "--workers", "10", "--workLimit", "3", "--outfile", outFileName)

	go func() {
		output, err := cmd.CombinedOutput()
		if err != nil {
			utils.FileLog.Info("execute command failed, output: , error: \n" + string(output) + err.Error())
			errorChannel <- err
			return
		}
		doneChannel <- true
	}()
	defer func() {
		_ = os.Remove(outFileName)
		if err != nil {
			utils.FileLog.Info("删除生产的图片文件失败, err: " + err.Error())
		}
	}()

	select {
	case <-time.After(30 * time.Second):
		utils.FileLog.Info("执行超过30秒 杀死超时进程")
		e := cmd.Process.Kill()
		if e != nil {
			fmt.Println("cmd kill err: ", e.Error())
			utils.FileLog.Info(fmt.Sprintf("cmd kill err: %s", e.Error()))
			errMsg = "图片生成失败"
			err = errors.New("图片生成失败, 执行超时" + e.Error())
			return
		}
		fmt.Println("timeout kill process")
	case <-doneChannel:
		fmt.Println("done")
	case e := <-errorChannel:
		errMsg = "文件上传失败"
		err = errors.New(fmt.Sprintf("execute command failure err: %s", e.Error()))
		fmt.Println("execute command failure err:" + e.Error())
		return
	}

	//上传到阿里云 和 minio
	ossClient := NewOssClient()
	if ossClient == nil {
		errMsg = "上传失败"
		err = errors.New("初始化OSS服务失败")
		return
	}
	resourceUrl, err = ossClient.UploadFile(outFileName, outFileName, "")
	if err != nil {
		errMsg = "文件上传失败"
		err = errors.New("文件上传失败,Err:" + err.Error())
		return
	}

	return
}