package file

import (
	"fmt"
	"net/http"
	"path/filepath"

	"nms_nbi/lib/core/utils/ctx"
	"nms_nbi/lib/dborm"
	"nms_nbi/lib/file"
	"nms_nbi/lib/log"
	"nms_nbi/lib/services"
	"nms_nbi/restagent/config"

	"github.com/gorilla/mux"
	"github.com/shirou/gopsutil/disk"
)

var (
	// parameter config management
	UriFile = config.DefaultUriPrefix + "/fileManagement/{apiVersion}/{location}/file"

	CustomUriFile = config.UriPrefix + "/fileManagement/{apiVersion}/{location}/file"

	// 获取磁盘列表
	UriDiskList = config.DefaultUriPrefix + "/fileManagement/{apiVersion}/files/diskList"

	// 获取文件列表
	UriListFiles = config.DefaultUriPrefix + "/fileManagement/{apiVersion}/files/listFiles"
)

// func init() {
// 	routes.Register("POST", UriFile, UploadFile, nil)
// 	routes.Register("GET", UriFile, DownloadFile, nil)
// 	routes.Register("DELETE", UriFile, DeleteFile, nil)
// }

func UploadFile(w http.ResponseWriter, r *http.Request) {
	log.Debug("UploadFile processing... ")

	_, err := services.CheckFrontValidRequest(w, r)
	if err != nil {
		log.Error("Http request error:", err)
		return
	}

	vars := mux.Vars(r)
	location := vars["location"]
	if location == "" {
		log.Error("location is empty")
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}
	params := r.URL.Query()
	rename, ok := params["rename"]
	if !ok {
		log.Info("rename parameter is not exist")
	}
	log.Debug("rename:", rename)

	var path, fileName string
	if len(rename) > 0 {
		fileName = rename[0]
	}
	if location == "upload" {
		path = config.GetYamlConfig().OMC.Upload
		fileName, err = services.HandleUploadFile(r, path, fileName)
		if err != nil {
			log.Error("Faile to HandleUploadFile:", err)
			services.ResponseInternalServerError500ProcessError(w, err)
			return
		}
	} else {
		path = config.GetYamlConfig().OMC.FrontUpload
		fileName, err = services.HandleUploadFile(r, path, fileName)
		if err != nil {
			log.Error("Faile to HandleUploadFile:", err)
			services.ResponseInternalServerError500ProcessError(w, err)
			return
		}
	}
	log.Debugf("upload file=%s to path=%s", fileName, path)

	services.ResponseStatusOK204NoContent(w)
	return
}

func DownloadFile(w http.ResponseWriter, r *http.Request) {
	log.Debug("DownloadFile processing... ")

	_, err := services.CheckFrontValidRequest(w, r)
	if err != nil {
		log.Error("Request error:", err)
		return
	}

	vars := mux.Vars(r)
	location := vars["location"]
	if location == "" {
		log.Error("location is empty")
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}

	// 全路径文件下载
	filePath := r.URL.Query().Get("path")
	if location == "path" && filePath != "" {
		// 截取文件路径
		dir := filepath.Dir(filePath)
		// 截取文件名
		fileName := filepath.Base(filePath)
		services.ResponseFileWithNameAndMD5(w, http.StatusOK, fileName, dir, "")
		return
	}

	params := r.URL.Query()
	fileNames, ok := params["loc"]
	if !ok {
		log.Info("loc parameter is not exist")
	}
	var path string
	if location == "upload" {
		path = config.GetYamlConfig().OMC.Upload
	} else {
		path = config.GetYamlConfig().OMC.FrontUpload
	}
	for _, fileName := range fileNames {
		services.ResponseFileWithNameAndMD5(w, http.StatusOK, fileName, path, "")
	}
	return
}

func DeleteFile(w http.ResponseWriter, r *http.Request) {
	log.Debug("DeleteFile processing... ")

	_, err := services.CheckFrontValidRequest(w, r)
	if err != nil {
		log.Error("Request error:", err)
		return
	}

	vars := mux.Vars(r)
	neType := vars["neType"]
	if neType == "" {
		log.Error("neType is empty")
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}

	services.ResponseStatusOK204NoContent(w)
	return
}

// 磁盘列表
func DiskList(w http.ResponseWriter, r *http.Request) {
	disks := make([]map[string]string, 0)

	partitions, err := disk.Partitions(false)
	if err != nil {
		services.ResponseWithJson(w, 200, disks)
	}

	for _, partition := range partitions {
		usage, err := disk.Usage(partition.Mountpoint)
		if err != nil {
			continue
		}
		disks = append(disks, map[string]string{
			"size":   file.FormatFileSize(float64(usage.Total)),
			"used":   file.FormatFileSize(float64(usage.Used)),
			"avail":  file.FormatFileSize(float64(usage.Free)),
			"pcent":  fmt.Sprintf("%.1f%%", usage.UsedPercent),
			"target": partition.Device,
		})
	}
	services.ResponseWithJson(w, 200, disks)
}

// 获取文件列表 /files/search
func ListFiles(w http.ResponseWriter, r *http.Request) {
	// json 請求參數獲取
	var bodyArgs FileOption
	err := ctx.ShouldBindJSON(r, &bodyArgs)
	if err != nil || dborm.DbClient.XEngine == nil {
		services.ResponseErrorWithJson(w, 400, err.Error())
		return
	}

	files, err := GetFileList(bodyArgs)
	if err != nil {
		services.ResponseErrorWithJson(w, 400, err.Error())
		return
	}
	services.ResponseWithJson(w, 200, files)
}
