package task

import (
	"bufio"
	"bytes"
	"context"
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"github.com/qiniu/api.v7/v7/auth/qbox"
	"github.com/qiniu/api.v7/v7/storage"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"io"
	"log-server/global"
	"log-server/model/common/request"
	"log-server/model/task"
	taskReq "log-server/model/task/request"
	"log-server/model/task/response"
	"log-server/utils"
	"mime/multipart"
	"path"
	"strconv"
	"strings"
	"time"
)

type TaskConfService struct {

}

func (e *TaskConfService) Upload(file response.UploadFileResponse) error {
	return global.GVA_DB.Table("upload_file").Create(&file).Error
}

//更改的上传文件函数
func (e *TaskConfService) UploadFileFunc(file *multipart.FileHeader, taskId string) (string, string, string, error) {
	// 读取文件后缀
	ext := path.Ext(file.Filename)
	// 读取文件名并加密
	name := strings.TrimSuffix(file.Filename, ext)
	name = utils.MD5V([]byte(name))
	// 拼接新文件名
	filename := name + "_" + time.Now().Format("20060102150405") + ext
	key := "shuyou/script/" + taskId + "/" + filename
	// 尝试创建此路径
	//mkdirErr := os.MkdirAll(global.GVA_CONFIG.Local.ScriptPath, os.ModePerm)
	//if mkdirErr != nil {
	//	global.GVA_LOG.Error("function os.MkdirAll() Filed", zap.Any("err", mkdirErr.Error()))
	//	return "", "", "", errors.New("function os.MkdirAll() Filed, err:" + mkdirErr.Error())
	//}
	// 拼接路径和文件名
	//p := global.GVA_CONFIG.Local.ScriptPath + "/" + filename
	//filepath := global.GVA_CONFIG.Local.ScriptPath + "/" + filename

	uploadErr := e.UploadFileToQiNiu(filename, taskId, file)
	if uploadErr != nil {
		global.GVA_LOG.Error("function UploadFileToQiNiu Filed", zap.Any("err", uploadErr.Error()))
		return "", "", "", errors.New("function UploadFileToQiNiu Filed, err:" + uploadErr.Error())
	}
	//f, openError := file.Open() // 读取文件
	f1, openErr := file.Open()	//	读取文件生成MD5值
	if  openErr != nil {
		global.GVA_LOG.Error("function file.Open() Filed", zap.Any("err", openErr.Error()))
		return "", "", "", errors.New("function file.Open() Filed, err:" + openErr.Error())
	}
	//defer f.Close() // 创建文件 defer 关闭
	defer f1.Close()
	//生成md5值
	md5h := md5.New()
	io.Copy(md5h, f1)
	md5String := hex.EncodeToString(md5h.Sum(nil))

	//
	//out, createErr := os.Create(p)
	//if createErr != nil {
	//	global.GVA_LOG.Error("function os.Create() Filed", zap.Any("err", createErr.Error()))
	//
	//	return "", "", "", errors.New("function os.Create() Filed, err:" + createErr.Error())
	//}
	//defer out.Close() // 创建文件 defer 关闭

	//_, copyErr := io.Copy(out, f) // 传输（拷贝）文件
	//fmt.Println("拷贝文件")
	//if copyErr != nil {
	//	global.GVA_LOG.Error("function io.Copy() Filed", zap.Any("err", copyErr.Error()))
	//	return "", "", "",  errors.New("function io.Copy() Filed, err:" + copyErr.Error())
	//}
	return key, filename, md5String, nil
}

func (e *TaskConfService) UploadFileToQiNiu(fileName string, taskId string, file *multipart.FileHeader) ( error) {
	accessKey := "B81Gsvry2StqKVE3txS-7v9GBBfqykC9zhebmxnW"
	secretKey := "YEZJuYcdeF7vRvzffxpopAVR-jMPZg9pZ-4IKTVW"
	mac := qbox.NewMac(accessKey, secretKey)
	bucket := "pinaishop"
	putPolicy := storage.PutPolicy{
		Scope: bucket,
	}
	key :="shuyou/script/" +  taskId + "/" + fileName


	upToken := putPolicy.UploadToken(mac)
	cfg := storage.Config{}
	// 空间对应的机房
	cfg.Region = &storage.ZoneHuanan
	// 是否使用https域名
	cfg.UseHTTPS = true
	// 上传是否使用CDN上传加速
	cfg.UseCdnDomains = false
	formUploader := storage.NewFormUploader(&cfg)
	ret := storage.PutRet{}
	putExtra := storage.PutExtra{
		//Params: map[string]string{
		//	"x:name": "github logo",
		//},
	}
	// Get the file size
	fileSize := file.Size
	f, openError := file.Open() // 读取文件
	if openError != nil  {
		global.GVA_LOG.Error("function file.Open() Filed", zap.Any("err", openError.Error()))
		return errors.New("function file.Open() Filed, err:" + openError.Error())
	}
	defer f.Close()
	// Read the file into a byte slice
	bs := make([]byte, fileSize)
	_, err := bufio.NewReader(f).Read(bs)
	if err != nil && err != io.EOF {
		fmt.Println(err)
		return errors.New("文件转化成字节数组错误, err:" + err.Error())
	}
	err = formUploader.Put(context.Background(), &ret, upToken, key, bytes.NewReader(bs), fileSize, &putExtra)
	if err != nil {
		fmt.Println(err)
		return errors.New("上传七牛云错误, err:" + err.Error())
	}
	fmt.Println(ret.Key, ret.Hash)
	return nil
}

//上传文件
func (e *TaskConfService) UploadFile(taskId int, user string, header *multipart.FileHeader) (file response.UploadFileResponse, err error) {
	//查询数据库记录数
	var count int64
	//获取最后一条记录
	var lastRecord response.UploadFileResponse
	var version int
	//定义下载前缀
	var prefix string = "http://cdn.pinaishop.kfzs.com/"

	global.GVA_DB.Table("upload_file").Where("task_id = ?", taskId).Count(&count)
	if count == 0 {
		version = 1
	} else {
		fmt.Println(count)
		global.GVA_DB.Table("upload_file").Where("task_id = ?", taskId).Order("id desc").Limit(1).Find(&lastRecord)
		fmt.Println(lastRecord)
		version = lastRecord.Version + 1

		recordArr := []response.UploadFileResponse{}
		global.GVA_DB.Table("upload_file").Where("task_id = ?", taskId).Find(&recordArr)
		fmt.Println(recordArr)
	}

	filePath, key, md5String, uploadErr := e.UploadFileFunc(header,strconv.Itoa(taskId) )
	if uploadErr != nil {
		panic(err)
	}
	s := strings.Split(header.Filename, ".")
	f := response.UploadFileResponse{
		TaskID: taskId,
		ResponsiblePerson: user,
		Url:  prefix + filePath,
		Name: header.Filename,
		Tag:  s[len(s)-1],
		Key:  key,
		Version: version,
		Md5String: md5String,
		State : 1,
	}
	return f, e.Upload(f)
}

//下载文件
func (e *TaskConfService) DownloadFile(taskId int, md5String string) (info response.DownloadFile, err error) {
	var file response.UploadFileResponse
	//改由存储至数据库的时候拼接前缀
	//var prefix string = global.GVA_CONFIG.PrefixUrl.PrefixLocal
	//数据库中无记录，即不需要更新
	err = global.GVA_DB.Table("upload_file").Where("task_id = ? and state = 1", taskId).Order("id desc").Limit(1).Find(&file).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		info = response.DownloadFile{
			Url: "",
			Md5String: "",
			Flag: false,
		}
		return info, errors.New("无对应脚本")
	}

	if file.Md5String == md5String {
		info = response.DownloadFile{
			Url: "",
			Md5String: "",
			Flag: false,
		}
	} else {
		fullUrl := file.Url
		info = response.DownloadFile{
			Url: fullUrl,
			Md5String: file.Md5String,
			Flag: true,
		}
	}

	return info, err

}

//条件查询脚本列表
func (e *TaskConfService) GetScriptList(script task.GameScriptResponse, info request.PageInfo, order string, desc bool) (list interface{}, total int64, err error) {
	//获取分页数据
	limit := info.PageSize
	offset := (info.Page - 1) * info.PageSize
	//绑定操作结构体
	db := global.GVA_DB.Table("upload_file").Model(&task.GameScriptResponse{})
	var scriptList []task.GameScriptResponse
	//条件查询
	if script.ResponsiblePerson != "" {
		db = db.Where("responsible_person = ?", script.ResponsiblePerson)
	}
	if script.TaskID != 0 {
		db = db.Where("task_id = ?", script.TaskID)
	}

	//先过滤在排序
	if err = db.Count(&total).Error; err != nil {
		return scriptList, total, err
	} else {
		//分页
		db.Limit(limit).Offset(offset)
		//判断是否有排序字段
		if order != "" {
			var orderStr string
			orderMap := make(map[string]bool, 1)
			orderMap["create_time"] = true
			orderMap["task_id"] = true
			orderMap["name"] = true
			orderMap["responsible_person"] = true
			orderMap["version"] = true
			if orderMap[order] {
				//合法排序字符
				if desc {
					orderStr = order + " desc"
				} else {
					orderStr = order
				}
			} else {
				//传入排序字段非法
				err = fmt.Errorf("传入非法字段 %v", order)
				return scriptList, total, err
			}
			err = db.Order(orderStr).Find(&scriptList).Error
		} else {
			//默认按照名字升序排序
			err = db.Order("name").Find(&scriptList).Error
		}
	}
	return scriptList, total, err
}

//更改脚本状态
func (e *TaskConfService) UpdateScriptStatus(c taskReq.UpdateScriptStatusRequest) (err error) {
	err = global.GVA_DB.Table("upload_file").Where("id = ?", c.Id).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return errors.New("请传入正确的Id")
	}
	err = global.GVA_DB.Table("upload_file").Where("id = ?", c.Id).Update("state", c.State).Error
	return err
}

//更改推送标准
func (e *TaskConfService) JudgeOperate(taskConf task.TaskConf) (err error) {
	//查找数据库中是否有这条记录
	var entity task.TaskConf
	err = global.GVA_DB.Model(&task.TaskConf{}).Where("task_id = ?", taskConf.TaskId).First(&entity).Error
	//如果没有，创建
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return global.GVA_DB.Model(&task.TaskConf{}).Create(&taskConf).Error
	}
	//如果有，更新
	return global.GVA_DB.Model(&task.TaskConf{}).Where("task_id = ?", taskConf.TaskId).Omit("task_id", "user").Updates(&taskConf).Error
}