package v1

import (
	"context"
	"designs/app/common/request"
	"designs/global"
	"designs/model"
	"designs/response"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/tencentyun/cos-go-sdk-v5"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"time"
)

func FileList(c *gin.Context) {
	form := request.Check(c, &struct {
		Dir    string `form:"dir" binding:"required"`
		Offset *int   `form:"offset" binding:"required"`
		Limit  *int   `form:"limit" binding:"required"`
		Search string `form:"search" binding:""`
	}{})

	query := global.App.DB.Table("file").Where("dir", form.Dir)
	if form.Search != "" {
		query = query.Where("fileName", "like", "%"+form.Search+"%")
	}
	var count int64
	err := query.Count(&count).Error
	if err != nil {
		response.Fail(c, 1001, err.Error())
		return
	}

	var files []model.File
	err = query.Offset(*form.Offset).Limit(*form.Limit).Scan(&files).Error
	if err != nil {
		response.Fail(c, 1002, err.Error())
		return
	}

	response.Success(c, gin.H{
		"count": count,
		"data":  files,
	})
}

func DirDownload(c *gin.Context) {
	form := request.Check(c, &struct {
		Dir string `form:"dir" binding:"required"`
	}{})

	data, err := DirExplode(form.Dir)
	if err != nil {
		response.Fail(c, 1001, err.Error())
		return
	}

	response.Success(c, gin.H{
		"data": data,
	})
}

func DirExplode(dir string) (map[string]interface{}, error) {

	data := make(map[string]interface{})

	var files []model.File
	err := global.App.DB.Table("file").Where("dir", dir).Scan(&files).Error

	if err != nil {
		return nil, err
	}

	for _, file := range files {
		if file.Type == 2 {
			data[file.FileName], _ = DirExplode(file.Dir)
		} else {
			data[file.FileName] = file.CosPath
		}
	}

	return data, nil
}

func FileDelete(c *gin.Context) {
	form := request.Check(c, &struct {
		FileId int `form:"fileId" json:"fileId" binding:"required"`
	}{})
	var file model.File
	global.App.DB.Table("file").Where("id", form.FileId).Find(&file)

	if file.Type == 1 {
		//删除本地文件和云端文件  （本地文件暂时不删除，作为备份）
		err := ServiceFileDelete(file.CosPath)
		if err != nil {
			response.Fail(c, 2001, "云端文件删除失败"+err.Error())
			return
		}
	}

	var d interface{}
	err := global.App.DB.Table("file").Where("id", form.FileId).Delete(d).Error
	if err != nil {
		response.Fail(c, 2001, err.Error())
		return
	}

	response.Success(c, gin.H{})
}

func LocalFileToService(c *gin.Context) {
	form := request.Check(c, &struct {
		Dir      string `form:"dir" json:"dir" binding:"required"`
		FilePath string `form:"filePath" json:"filePath" binding:"required"`
	}{})

	path, err := FileToService(form.FilePath)
	if err != nil {
		response.Fail(c, 1004, err.Error())
		return
	}

	now := model.XTime{
		Time: time.Now(),
	}

	//存储到mysql
	err = global.App.DB.Table("file").Create(&model.File{
		CreatedAt: now,
		UpdatedAt: now,
		FileName:  filepath.Base(form.FilePath),
		LocalPath: form.FilePath,
		Type:      1,
		Dir:       form.Dir,
		CosPath:   path,
	}).Error
	if err != nil {
		response.Fail(c, 2001, err.Error())
		return
	}

	response.Success(c, gin.H{
		"file_path": path,
	})
}

func UploadToCos(c *gin.Context) {
	// 获取文件
	file, err := c.FormFile("file")
	if err != nil {
		response.Fail(c, 400, "未选择文件")
		return
	}

	//获取dir
	dir := c.PostForm("dir")
	if dir == "" {
		dir = "/"
	} else if dir != "/" { //格式化
		dir = "/" + strings.Trim(dir, "/") + "/"
	}

	// 存储路径生成
	saveDir := fmt.Sprintf("uploads/%s", dir)
	os.MkdirAll(saveDir, 0755)

	savePath := filepath.Join(saveDir, file.Filename)
	// 保存文件
	if err := c.SaveUploadedFile(file, savePath); err != nil {
		response.Fail(c, 500, "文件保存失败")
		return
	}

	path, err := FileToService(savePath)
	if err != nil {
		response.Fail(c, 1004, err.Error())
		return
	}

	now := model.XTime{
		Time: time.Now(),
	}

	//存储文件夹
	var dirFile model.File

	base := filepath.Base(dir)
	dirPath := strings.TrimSuffix(dir, base+"/")

	fmt.Println("dirPath", dirPath)
	global.App.DB.Table("file").Where("type", 2).Where("fileName", base).Where("dir", dirPath).First(&dirFile)
	if dirFile.Id == 0 {
		err := global.App.DB.Table("file").Create(&model.File{
			CreatedAt: now,
			UpdatedAt: now,
			FileName:  base,
			Dir:       dirPath,
			LocalPath: "",
			Type:      2,
			CosPath:   "",
		}).Error
		if err != nil {
			response.Fail(c, 2001, err.Error())
			return
		}
	}

	//存储到mysql
	var files model.File
	global.App.DB.Table("file").Where("fileName", filepath.Base(savePath)).Where("dir", dir).Find(&files)

	if files.Id != 0 {
		err = global.App.DB.Table("file").Where("id", files.Id).Updates(map[string]interface{}{
			"localPath": savePath,
			"updatedAt": now,
			"fileName":  filepath.Base(savePath),
			"dir":       dir,
			"cosPath":   path,
		}).Error
	} else {
		err = global.App.DB.Table("file").Create(&model.File{
			CreatedAt: now,
			UpdatedAt: now,
			FileName:  filepath.Base(savePath),
			LocalPath: savePath,
			Type:      1,
			Dir:       dir,
			CosPath:   path,
		}).Error
	}

	if err != nil {
		response.Fail(c, 2001, err.Error())
		return
	}

	response.Success(c, gin.H{
		"file_path": path,
	})
}

func CreateDir(c *gin.Context) {
	form := request.Check(c, &struct {
		Dir     string `form:"dir" json:"dir" binding:"required"`
		DirName string `form:"dirName" json:"dirName" binding:"required"`
	}{})

	count := strings.Count(form.Dir, "/")
	if count >= 3 {
		response.Fail(c, 1002, "文件夹的层级不能超过三级")
		return
	}

	now := model.XTime{
		Time: time.Now(),
	}

	//存储到mysql
	err := global.App.DB.Table("file").Create(&model.File{
		CreatedAt: now,
		UpdatedAt: now,
		FileName:  form.DirName,
		Dir:       form.Dir,
		LocalPath: "",
		Type:      2,
		CosPath:   "",
	}).Error
	if err != nil {
		response.Fail(c, 2001, err.Error())
		return
	}

	response.Success(c, gin.H{})
}

const CosUrl = "https://chunhao-1257323087.cos.ap-shanghai.myqcloud.com"
const CosServiceUrl = "https://service.cos.myqcloud.com"
const SecretID = "AKIDgQ2TzTq381nQrAJKBC8tSqCNM9lBQTQB"
const SecretKey = "gBVWO4dzCD5qeKoy30phTBi7NXYYM2b0"

func FileToService(filePath string) (string, error) {
	// 将 examplebucket-1250000000 和 COS_REGION 修改为用户真实的信息
	// 存储桶名称，由 bucketname-appid 组成，appid 必须填入，可以在 COS 控制台查看存储桶名称。https://console.cloud.tencent.com/cos5/bucket
	// COS_REGION 可以在控制台查看，https://console.cloud.tencent.com/cos5/bucket, 关于地域的详情见 https://cloud.tencent.com/document/product/436/6224
	u, _ := url.Parse(CosUrl)
	// 用于 Get Service 查询，默认全地域 service.cos.myqcloud.com
	su, _ := url.Parse(CosServiceUrl)
	b := &cos.BaseURL{BucketURL: u, ServiceURL: su}
	// 1.永久密钥
	client := cos.NewClient(b, &http.Client{
		Transport: &cos.AuthorizationTransport{
			SecretID:  SecretID,  // 用户的 SecretId，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参考 https://cloud.tencent.com/document/product/598/37140
			SecretKey: SecretKey, // 用户的 SecretKey，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参考 https://cloud.tencent.com/document/product/598/37140
		},
	})

	key := filepath.Base(filePath)
	fmt.Println("key", key)
	fmt.Println("filePath", filePath)
	res, _, err := client.Object.Upload(
		context.Background(), filePath, filePath, nil,
	)
	fmt.Println(res)
	if err != nil {
		return "", err
	}

	//ourl := client.Object.GetObjectURL(key)

	return res.Location, nil
}

func ServiceFileDelete(cosPath string) error {
	u, _ := url.Parse(CosUrl)
	// 用于 Get Service 查询，默认全地域 service.cos.myqcloud.com
	su, _ := url.Parse(CosServiceUrl)
	b := &cos.BaseURL{BucketURL: u, ServiceURL: su}
	// 1.永久密钥
	client := cos.NewClient(b, &http.Client{
		Transport: &cos.AuthorizationTransport{
			SecretID:  SecretID,  // 用户的 SecretId，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参考 https://cloud.tencent.com/document/product/598/37140
			SecretKey: SecretKey, // 用户的 SecretKey，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参考 https://cloud.tencent.com/document/product/598/37140
		},
	})

	res, err := client.Object.Delete(
		context.Background(), cosPath,
	)
	fmt.Println(res)
	if err != nil {
		return err
	}

	return nil
}
