package controller

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"iot_manager_service/app/file/dao"
	"iot_manager_service/app/file/model"
	"iot_manager_service/app/file/service"
	dao2 "iot_manager_service/app/user/dao"
	"iot_manager_service/util/cache"
	"iot_manager_service/util/common"
	"iot_manager_service/util/token"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

var FileController = new(file)

type file struct{}

func (f *file) Upload(c *gin.Context) {
	header := c.GetHeader("Authorization")
	claims, _ := token.JwtClaims.ParseJwtToken(header)
	uploader, _ := strconv.Atoi(claims.ID)

	//校验权限 -- 4代表上传权限
	authUpload := CheckUserAuth(uploader, "4")
	if !authUpload {
		c.JSON(http.StatusForbidden, common.StatusForbidden("您没有上传权限，请联系管理员。", nil))
		return
	}

	// 获取表单字段的值
	categoryName := c.PostForm("categoryName")
	iv := c.PostForm("iv")
	str := c.PostForm("authId")
	authId := strings.Replace(str, ",", "", -1)

	formFile, err := c.FormFile("file")
	if err != nil {
		c.JSON(http.StatusOK, common.ParamsInvalidResponse("获取文件数据失败", nil))
		return
	}
	//获取后缀
	sufx := path.Ext(formFile.Filename)
	//利用时间戳生成文件名
	fileNameInt := time.Now().Unix()
	fileNameStr := strconv.FormatInt(fileNameInt, 10)
	//新的文件名
	newfileName := fileNameStr + sufx

	currentDir, _ := os.Getwd()
	parentDir := filepath.Dir(currentDir)
	folderPath := filepath.Join(parentDir, "uploadfiles")
	_, err = os.Stat(folderPath)
	if os.IsNotExist(err) {
		os.Mkdir(folderPath, os.ModePerm)
	}
	//保存文件
	filePath := filepath.Join(folderPath, "/", newfileName)
	c.SaveUploadedFile(formFile, filePath)

	savePath := "/uploadfiles/" + newfileName
	currentTimeValue := time.Now()
	upload := service.FileService.Upload(dao.File{
		OriginalName:  strings.TrimSuffix(formFile.Filename, filepath.Ext(formFile.Filename)),
		EncryptedName: formFile.Filename,
		SavePath:      savePath,
		CategoryName:  categoryName,
		AuthId:        authId,
		SuffixName:    path.Ext(formFile.Filename),
		UploadTime:    &currentTimeValue,
		Uploader:      uploader,
		Icon:          strings.TrimPrefix(path.Ext(formFile.Filename), ".") + ".png",
		Iv:            iv,
	})
	c.JSON(http.StatusOK, upload)

}

func (f *file) Distribute(c *gin.Context) {
	//获取当前用户
	header := c.GetHeader("Authorization")
	claims, _ := token.JwtClaims.ParseJwtToken(header)
	nowSysUser, _ := cache.GetNowSysUser(claims.ID)

	var reqUserFile model.ReqSysUserFile
	err := c.ShouldBindJSON(&reqUserFile)
	if err != nil {
		c.JSON(http.StatusOK, common.ParamsInvalidResponse(err.Error(), nil))
		return
	}
	distribute := service.FileService.Distribute(&reqUserFile, int(nowSysUser.ID))
	c.JSON(http.StatusOK, distribute)
}

func (f *file) GetSysUserFiles(c *gin.Context) {
	header := c.GetHeader("Authorization")
	claims, _ := token.JwtClaims.ParseJwtToken(header)

	var search model.SearchSysUserFiles
	err := c.ShouldBindJSON(&search)
	if err != nil {
		c.JSON(http.StatusOK, common.ParamsInvalidResponse(err.Error(), nil))
		return
	}

	files := service.FileService.GetSysUserFiles(claims.ID, search)
	c.JSON(http.StatusOK, files)
}

// 转发文件
func (f *file) ForwardingFile(c *gin.Context) {
	header := c.GetHeader("Authorization")
	claims, _ := token.JwtClaims.ParseJwtToken(header)
	uid, _ := strconv.Atoi(claims.ID)

	requsers := model.ReqSysUsers{}
	if err := c.ShouldBind(&requsers); err != nil {
		c.JSON(http.StatusOK, common.ParamsInvalidResponse(err.Error(), nil))
		return
	}

	authView := CheckUserAuth(uid, "3")
	if !authView {
		c.JSON(http.StatusForbidden, common.StatusForbidden("您没有【转发】权限，请联系管理员。", nil))
		return
	}

	for _, fid := range requsers.FilesId {
		auth, time, name := CheckFileAuth(uid, fid, "3")
		if time {
			c.JSON(http.StatusForbidden, common.StatusForbidden(fmt.Sprintf("文件【%s】操作时间已过，无权操作。", name), nil))
			return
		}
		if auth {
			c.JSON(http.StatusForbidden, common.StatusForbidden(fmt.Sprintf("文件【%s】不支持转发操作，请联系管理员。", name), nil))
			return
		}
	}

	forwardingFile := service.FileService.ForwardingFile(uid, requsers.FilesId, requsers.SysUsersId)
	c.JSON(http.StatusOK, forwardingFile)
}

// 查看文件
func (f *file) ViewFile(c *gin.Context) {
	//校验权限
	header := c.GetHeader("Authorization")
	claims, _ := token.JwtClaims.ParseJwtToken(header)
	uid, _ := strconv.Atoi(claims.ID)

	authView := CheckUserAuth(uid, "1")
	if !authView {
		c.JSON(http.StatusForbidden, common.StatusForbidden("您没有【查看】权限，请联系管理员。", nil))
		return
	}

	fileId := c.Query("fileId")
	fid, _ := strconv.Atoi(fileId)
	auth, time, name := CheckFileAuth(uid, fid, "1")
	if time {
		c.JSON(http.StatusForbidden, common.StatusForbidden(fmt.Sprintf("文件【%s】操作时间已过，无权操作。", name), nil))
		return
	}
	if auth {
		c.JSON(http.StatusForbidden, common.StatusForbidden(fmt.Sprintf("文件【%s】不支持查看操作，请联系管理员。", name), nil))
		return
	}
	service.FileService.GetFile(fileId, c)
}

// 下载文件
func (f *file) DownloadFile(c *gin.Context) {
	//校验权限
	header := c.GetHeader("Authorization")
	claims, _ := token.JwtClaims.ParseJwtToken(header)
	uid, _ := strconv.Atoi(claims.ID)

	authView := CheckUserAuth(uid, "2")
	if !authView {
		c.JSON(http.StatusForbidden, common.StatusForbidden("您没有【下载】权限，请联系管理员。", nil))
		return
	}

	fileId := c.Query("fileId")
	fid, _ := strconv.Atoi(fileId)
	auth, time, name := CheckFileAuth(uid, fid, "2")
	if time {
		c.JSON(http.StatusForbidden, common.StatusForbidden(fmt.Sprintf("文件【%s】操作时间已过，无权操作。", name), nil))
		return
	}
	if auth {
		c.JSON(http.StatusForbidden, common.StatusForbidden(fmt.Sprintf("文件【%s】不支持下载操作，请联系管理员。", name), nil))
		return
	}
	service.FileService.GetFile(fileId, c)
}

func (f *file) GetMyUploadFiles(c *gin.Context) {
	header := c.GetHeader("Authorization")
	claims, _ := token.JwtClaims.ParseJwtToken(header)
	files := service.FileService.GetMyUploadFiles(claims.ID)
	c.JSON(http.StatusOK, files)
}

func CheckUserAuth(uid int, authstr string) bool {
	userdao := dao2.SysUser{}
	user, _ := userdao.GetNowSysUser(uid)
	if !strings.Contains(user.AuthId, authstr) {
		return false
	}
	return true
}

func CheckFileAuth(uid, fileid int, authstr string) (bool, bool, string) {
	filedao := &dao.File{}
	fileInfo, _ := filedao.GetFileInfo(fileid, uid)

	targetTime, _ := time.Parse("2006-01-02 15:04:05 -0700 MST", fileInfo.EffectiveDate.String())
	now := time.Now()
	return !strings.Contains(fileInfo.AuthId, authstr), !now.Before(targetTime), fileInfo.OriginalName
}
