package file_export

import (
	"encoding/json"
	"net/http"
	"os"
	"path/filepath"

	"be.ems/lib/file"
	"be.ems/lib/log"
	"be.ems/lib/services"
	"be.ems/src/framework/datasource"
	"be.ems/src/framework/i18n"
	"be.ems/src/framework/utils/ctx"
	"be.ems/src/modules/crontask/processor/exportUEData"
	"github.com/gin-gonic/gin"
)

type SysJobResponse struct {
	SysJob
	TableName    string `json:"tableName"`
	TableDisplay string `json:"tableDisplay"`
	FilePath     string `json:"filePath"`
}

// GetFileExportTable 获取文件导出任务列表
func (m *SysJob) GetFileExportTable(c *gin.Context) {
	var results []SysJob

	err := datasource.DefaultDB().Table(m.TableName()).Where("invoke_target=? and status=1", INVOKE_FILE_EXPORT).
		Find(&results).Error
	if err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}
	language := ctx.AcceptLanguage(c)
	var response []SysJobResponse
	for _, job := range results {
		params := make([]exportUEData.BarParams, 0)
		if err := json.Unmarshal([]byte(job.TargetParams), &params); err != nil {
			c.JSON(http.StatusOK, services.ErrResp(err.Error()))
			return
		}
		for _, param := range params {
			TableDisplay := i18n.TKey(language, "table."+param.TableName)
			if TableDisplay == "" {
				TableDisplay = param.TableName
			}
			response = append(response, SysJobResponse{
				SysJob:       job,
				TableName:    param.TableName,
				TableDisplay: TableDisplay,
				FilePath:     param.FilePath,
			})
		}
	}
	c.JSON(http.StatusOK, services.DataResp(response))
}

func (m *FileExport) GetFileList(c *gin.Context) {
	var querys FileExportQuery

	if err := c.ShouldBindQuery(&querys); err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}

	files, err := file.GetFileInfo(querys.Path, querys.Suffix)
	if err != nil {
		log.Error("failed to GetFileInfo:", err)
		c.JSON(http.StatusOK, services.ErrResp("not found path file"))
		return
	}

	// split files list
	lenNum := int64(len(files))
	start := (querys.PageNum - 1) * querys.PageSize
	end := start + querys.PageSize
	var splitList []file.FileInfo
	if start >= lenNum {
		splitList = []file.FileInfo{}
	} else if end >= lenNum {
		splitList = files[start:]
	} else {
		splitList = files[start:end]
	}
	total := len(files)
	c.JSON(http.StatusOK, services.TotalDataResp(splitList, total))
}

func (m *FileExport) Total(c *gin.Context) {
	dir := c.Query("path")

	fileCount, dirCount, err := file.GetFileAndDirCount(dir)
	if err != nil {
		log.Error("failed to GetFileAndDirCount:", err)
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}
	total := fileCount + dirCount
	c.JSON(http.StatusOK, services.TotalResp(int64(total)))
}

func (m *FileExport) DownloadHandler(c *gin.Context) {
	dir := c.Query("path")
	fileName := c.Param("fileName")
	filePath := filepath.Join(dir, fileName)

	file, err := os.Open(filePath)
	if err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}
	defer file.Close()

	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}

	c.Header("Content-Disposition", "attachment; filename="+fileName)
	c.Header("Content-Type", "application/octet-stream")
	c.File(filePath)
}

func (m *FileExport) Delete(c *gin.Context) {
	fileName := c.Param("fileName")
	dir := c.Query("path")
	filePath := filepath.Join(dir, fileName)

	if err := os.Remove(filePath); err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}
	c.JSON(http.StatusNoContent, nil) // 204 No Content
}
