package admin

import (
	"archive/zip"
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"server/dao"
	"server/global"
	"server/model/common/request"
	"server/model/common/response"
	"strconv"
)

type ProjectApi struct{}

func (pa *ProjectApi) QueryProjectList(c *gin.Context) {
	var search request.SearchProject
	err := c.ShouldBindJSON(&search)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryProjectList ====== " + err.Error())
		return
	}

	list, total, err := projectService.QueryProjectList(search)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryProjectList ====== " + err.Error())
		return
	}

	response.OkWithDetailed(response.PageResult{
		List:     list,
		Total:    total,
		Page:     search.PageInfo.Page,
		PageSize: search.PageInfo.PageSize,
	}, "获取成功", c)
}

func (pa *ProjectApi) QueryProjectByCode(c *gin.Context) {
	code := c.Query("code")
	if code == "" {
		response.FailWithMessage("编号不能为空", c)
		return
	}
	project, err := projectService.QueryProjectByCode(code)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryProjectByCode ====== " + err.Error())
		return
	}
	response.OkWithData(project, c)
}

func (pa *ProjectApi) QueryFileList(c *gin.Context) {
	var info request.SearchProjectFileList
	err := c.ShouldBindJSON(&info)
	if err != nil {
		response.FailWithMessage("错误", c)
		global.GVA_LOG.Error("QueryFileList ====== " + err.Error())
		return
	}
	list, total, err := projectService.QueryFileList(info)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryFileList ====== " + err.Error())
		return
	}

	response.OkWithDetailed(response.PageResult{
		List:     list,
		Total:    total,
		Page:     info.PageInfo.Page,
		PageSize: info.PageInfo.PageSize,
	}, "获取成功", c)
}

func (pa *ProjectApi) QueryAllProject(c *gin.Context) {
	projects, err := projectService.QueryAllProject()
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithData(projects, c)
}

func (pa *ProjectApi) QueryProjectsInfo(c *gin.Context) {
	sum, totalProject, completeProject, unCompleteProject, err := projectService.QueryProjectsInfo()
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithData(gin.H{
		"sum":               sum,
		"totalProject":      totalProject,
		"completeProject":   completeProject,
		"unCompleteProject": unCompleteProject,
	}, c)
}

func (pa *ProjectApi) QueryProjectState(c *gin.Context) {
	states, err := projectService.QueryProjectState()
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryProjectState ====== " + err.Error())
		return
	}
	response.OkWithData(states, c)
}

func (pa *ProjectApi) QueryWorkingHours(c *gin.Context) {
	code := c.Query("code")
	hours, err := projectService.QueryWorkingHours(code)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithData(hours, c)
}

func (pa *ProjectApi) QueryWorkingHoursList(c *gin.Context) {
	var info request.SearchWorkingHours
	err := c.ShouldBindJSON(&info)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryWorkingHoursList ====== " + err.Error())
		return
	}
	list, total, err := projectService.QueryWorkingHoursList(info)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryWorkingHoursList ====== " + err.Error())
		return
	}
	response.OkWithDetailed(response.PageResult{
		List:     list,
		Total:    total,
		Page:     info.PageInfo.Page,
		PageSize: info.PageInfo.PageSize,
	}, "获取成功", c)
}

func (pa *ProjectApi) QueryWorkingHoursSum(c *gin.Context) {
	var info request.SearchWorkingHours
	err := c.ShouldBindJSON(&info)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryWorkingHoursSum ====== " + err.Error())
		return
	}
	list, total, err := projectService.QueryWorkingHoursSum(info)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryWorkingHoursSum ====== " + err.Error())
		return
	}
	response.OkWithDetailed(response.PageResult{
		List:     list,
		Total:    total,
		Page:     info.PageInfo.Page,
		PageSize: info.PageInfo.PageSize,
	}, "获取成功", c)
}

func (pa *ProjectApi) QueryCollections(c *gin.Context) {
	code := c.Query("code")
	collections, err := projectService.QueryCollections(code)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryCollections ====== " + err.Error())
		return
	}
	response.OkWithData(collections, c)
}

func (pa *ProjectApi) QueryCollectionList(c *gin.Context) {
	var info request.SearchProjectList
	err := c.ShouldBindJSON(&info)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryCollectionList ====== " + err.Error())
		return
	}
	list, total, err := projectService.QueryCollectionList(info)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryCollectionList ====== " + err.Error())
		return
	}
	response.OkWithDetailed(response.PageResult{
		List:     list,
		Total:    total,
		Page:     info.PageInfo.Page,
		PageSize: info.PageInfo.PageSize,
	}, "获取成功", c)
}

func (pa *ProjectApi) QueryReimbursementList(c *gin.Context) {
	var info request.SearchProjectList
	err := c.ShouldBindJSON(&info)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryReimbursementList ====== " + err.Error())
		return
	}
	list, total, err := projectService.QueryReimbursementList(info)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryReimbursementList ====== " + err.Error())
		return
	}
	response.OkWithDetailed(response.PageResult{
		List:     list,
		Total:    total,
		Page:     info.PageInfo.Page,
		PageSize: info.PageInfo.PageSize,
	}, "获取成功", c)
}

func (pa *ProjectApi) QueryReimbursement(c *gin.Context) {
	code := c.Query("code")
	reimbursement, err := projectService.QueryReimbursement(code)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryReimbursement ====== " + err.Error())
		return
	}
	response.OkWithData(reimbursement, c)
}

func (pa *ProjectApi) QueryProjectSum(c *gin.Context) {
	code := c.Query("code")
	sum, err := projectService.QueryProjectSum(code)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("QueryProjectSum ====== " + err.Error())
		return
	}
	response.OkWithData(sum, c)
}

func (pa *ProjectApi) CreateProject(c *gin.Context) {
	form, err := c.MultipartForm()
	files := form.File["file"]
	if err != nil {
		response.FailWithMessage("失败", c)
		return
	}
	projectJson := c.PostForm("project")
	fmt.Println(projectJson)
	var project dao.Project
	err = json.Unmarshal([]byte(projectJson), &project)
	if err != nil {
		response.FailWithMessage("JSON失败", c)
		return
	}
	for _, file := range files {
		dst := file.Filename
		newdst := uuid.New().String() + filepath.Ext(file.Filename)
		var path = "./uploads/file/项目/" + project.Code + "/项目前期文件" + "/" + newdst
		projectFile := dao.ProjectFile{
			ProjectCode: project.Code,
			Name:        dst,
			Key:         newdst,
			Path:        path,
			Genre:       1,
		}

		project.Files = append(project.Files, projectFile)

		// gin 简单做了封装,拷贝了文件流
		if err := c.SaveUploadedFile(file, path); err != nil {
			response.FailWithMessage("上传失败", c)
			return
		}
	}
	err = projectService.CreateProject(project)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	response.OkWithMessage("创建成功", c)
}

func (pa *ProjectApi) CreateProjectFile(c *gin.Context) {
	form, err := c.MultipartForm()
	if err != nil {
		response.FailWithMessage("失败", c)
		return
	}
	files := form.File["file"]

	genre := c.PostForm("genre")

	if len(genre) <= 0 {
		response.FailWithMessage("类型为空", c)
		return
	}

	code := c.PostForm("code")
	genreId, err := strconv.Atoi(genre)
	if err != nil {
		response.FailWithMessage("错误", c)
		global.GVA_LOG.Error("CreateProjectFile ====== " + err.Error())
		return
	}
	fileGenre, err := fileService.QueryFileGenreById(genreId)
	if err != nil {
		response.FailWithMessage("错误", c)
		global.GVA_LOG.Error("CreateProjectFile ====== " + err.Error())
		return
	}
	for _, file := range files {
		dst := file.Filename
		newdst := uuid.New().String() + filepath.Ext(file.Filename)
		var path = "./uploads/file/项目/" + code + "/" + fileGenre.Name + "/" + newdst
		projectFile := dao.ProjectFile{
			ProjectCode: code,
			Name:        dst,
			Path:        path,
			Key:         newdst,
			Genre:       genreId,
		}

		// gin 简单做了封装,拷贝了文件流
		if err := c.SaveUploadedFile(file, path); err != nil {
			response.FailWithMessage("上传失败", c)
			return
		}
		err = projectService.CreateProjectFile(projectFile)
		if err != nil {
			response.FailWithMessage("上传失败", c)
			return
		}
	}

	response.OkWithMessage("上传成功", c)
}

func (pa *ProjectApi) CreateProjectState(c *gin.Context) {
	var projectState dao.ProjectState
	err := c.ShouldBindJSON(&projectState)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("CreateProjectState ====== " + err.Error())
		return
	}
	err = projectService.CreateProjectState(projectState)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("CreateProjectState ====== " + err.Error())
		return
	}
	response.OkWithMessage("新增成功", c)
}

func (pa *ProjectApi) CreateWorkingHours(c *gin.Context) {
	var working dao.ProjectWorkingHours
	err := c.ShouldBindJSON(&working)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	err = projectService.CreateOrUpdateWorkingHours(working)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithMessage("更新成功", c)
}

func (pa *ProjectApi) CreateCollection(c *gin.Context) {
	var collection dao.Collection
	err := c.ShouldBindJSON(&collection)
	if err != nil {
		response.FailWithMessage("错误", c)
		global.GVA_LOG.Error("CreateCollection ====== " + err.Error())
		return
	}
	err = projectService.CreateCollection(collection)
	if err != nil {
		response.FailWithMessage("错误", c)
		global.GVA_LOG.Error("CreateCollection ====== " + err.Error())
		return
	}
	response.OkWithMessage("创建成功", c)
}

func (pa *ProjectApi) CreateReimbursement(c *gin.Context) {
	var reimbursement dao.Reimbursement
	err := c.ShouldBindJSON(&reimbursement)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("CreateReimbursement ====== " + err.Error())
		return
	}
	err = projectService.CreateReimbursement(reimbursement)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("CreateReimbursement ====== " + err.Error())
		return
	}
	response.OkWithMessage("新建成功", c)
}

func (pa *ProjectApi) UpdateProject(c *gin.Context) {
	var project dao.Project
	err := c.ShouldBindJSON(&project)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	err = projectService.UpdateProject(project)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithMessage("更新成功", c)
}

func (pa *ProjectApi) UpdateProjectState(c *gin.Context) {
	var projectState dao.ProjectState
	err := c.ShouldBindJSON(&projectState)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("UpdateProjectState ====== " + err.Error())
		return
	}
	err = projectService.UpdateProjectState(projectState)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("UpdateProjectState ====== " + err.Error())
		return
	}
	response.OkWithMessage("更新成功", c)
}

func (pa *ProjectApi) UpdateWorkingHours(c *gin.Context) {
	var working dao.ProjectWorkingHours
	err := c.ShouldBindJSON(&working)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	err = projectService.UpdateWorkingHours(working)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithMessage("更新成功", c)
}

func (pa *ProjectApi) UpdateCollection(c *gin.Context) {
	var collection dao.Collection
	err := c.ShouldBindJSON(&collection)
	if err != nil {
		response.FailWithMessage("错误", c)
		global.GVA_LOG.Error("UpdateCollection ====== " + err.Error())
		return
	}
	err = projectService.UpdateCollection(collection)
	if err != nil {
		response.FailWithMessage("错误", c)
		global.GVA_LOG.Error("UpdateCollection ====== " + err.Error())
	}
	response.OkWithMessage("修改成功", c)
}

func (pa *ProjectApi) UpdateReimbursement(c *gin.Context) {
	var reimbursement dao.Reimbursement
	err := c.ShouldBindJSON(&reimbursement)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("UpdateReimbursement ====== " + err.Error())
		return
	}
	err = projectService.UpdateReimbursement(reimbursement)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("UpdateReimbursement ====== " + err.Error())
		return
	}
	response.OkWithMessage("修改成功", c)
}

func (pa *ProjectApi) DeleteProject(c *gin.Context) {
	code := c.Query("code")
	if code == "" {
		response.FailWithMessage("编号不能为空", c)
		return
	}
	err := projectService.DeleteProject(code)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithMessage("删除成功", c)
}

func (pa *ProjectApi) DeleteProjectFile(c *gin.Context) {
	id := c.Query("id")
	path := c.Query("path")
	i, err := strconv.Atoi(id)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	err = os.Remove(path)
	if err != nil {
		// 如果发生错误，打印错误信息
		response.FailWithMessage("删除文件时发生错误", c)
		global.GVA_LOG.Error("删除文件时发生错误: " + err.Error())
		return
	}

	err = projectService.DeleteProjectFile(uint(i))
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithMessage("删除成功", c)
}

func (pa *ProjectApi) DeleteProjectFiles(c *gin.Context) {
	var info request.SearchProjectFileList
	err := c.ShouldBindJSON(&info)
	fmt.Println(info)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	files, err := projectService.QueryFilesByNameOrGenre(info)
	if err != nil {
		response.FailWithMessage("错误", c)
		global.GVA_LOG.Error("ProjectFilesDownload ====== " + err.Error())
		return
	}

	fmt.Println(files)
	for _, file := range files {
		err = os.Remove(file.Path)
		if err != nil {
			// 如果发生错误，打印错误信息
			response.FailWithMessage("删除文件时发生错误", c)
			global.GVA_LOG.Error("删除文件时发生错误: " + err.Error())
			return
		}

		err = projectService.DeleteProjectFile(file.ID)
		if err != nil {
			response.FailWithMessage(err.Error(), c)
			return
		}
	}

	response.OkWithMessage("删除成功", c)
}

func (pa *ProjectApi) DeleteProjectState(c *gin.Context) {
	var projectState dao.ProjectState
	err := c.ShouldBindJSON(&projectState)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("DeleteProjectState ====== " + err.Error())
		return
	}
	err = projectService.DeleteProjectState(projectState)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("DeleteProjectState ====== " + err.Error())
		return
	}
	response.OkWithMessage("删除成功", c)
}

func (pa *ProjectApi) DeleteWorkingHours(c *gin.Context) {
	var working dao.ProjectWorkingHours
	err := c.ShouldBindJSON(&working)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	err = projectService.DeleteWorkingHours(working)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithMessage("删除成功", c)
}

func (pa *ProjectApi) DeleteCollection(c *gin.Context) {
	var collection dao.Collection
	err := c.ShouldBindJSON(&collection)
	if err != nil {
		response.FailWithMessage("错误", c)
		global.GVA_LOG.Error("DeleteCollection ====== " + err.Error())
		return
	}
	err = projectService.DeleteCollection(collection)
	if err != nil {
		response.FailWithMessage("错误", c)
		global.GVA_LOG.Error("DeleteCollection ====== " + err.Error())
		return
	}
	response.OkWithMessage("删除成功", c)
}

func (pa *ProjectApi) DeleteReimbursement(c *gin.Context) {
	var reimbursement dao.Reimbursement
	err := c.ShouldBindJSON(&reimbursement)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("DeleteReimbursement ====== " + err.Error())
		return
	}
	err = projectService.DeleteReimbursement(reimbursement)
	if err != nil {
		response.FailWithMessage("失败", c)
		global.GVA_LOG.Error("DeleteReimbursement ====== " + err.Error())
		return
	}
	response.OkWithMessage("删除成功", c)
}

func (pa *ProjectApi) ProjectFilesDownload(c *gin.Context) {
	var info request.SearchProjectFileList
	err := c.ShouldBindJSON(&info)
	if err != nil {
		response.FailWithMessage("错误", c)
		global.GVA_LOG.Error("ProjectFilesDownload ====== " + err.Error())
		return
	}
	files, err := projectService.QueryFilesByNameOrGenre(info)
	if err != nil {
		response.FailWithMessage("错误", c)
		global.GVA_LOG.Error("ProjectFilesDownload ====== " + err.Error())
		return
	}

	zipBuffer := &bytes.Buffer{}
	zipWriter := zip.NewWriter(zipBuffer)

	for _, file := range files {
		err := addFileToZip(zipWriter, file.Path)
		if err != nil {
			response.FailWithMessage("错误", c)
			global.GVA_LOG.Error("ProjectFilesDownload ====== " + err.Error())
			return
		}
	}
	// 确保所有文件都被写入
	if err := zipWriter.Close(); err != nil {
		response.FailWithMessage("错误", c)
		global.GVA_LOG.Error("ProjectFilesDownload ====== " + err.Error())
		return
	}
	// 设置响应头
	c.Header("Content-Description", "File Transfer")
	c.Header("Content-Type", "application/zip")
	c.Header("Content-Transfer-Encoding", "binary")
	c.Header("Content-Disposition", "filename=files.zip")
	c.Header("Cache-Control", "must-revalidate")
	c.Header("Pragma", "public")
	// 发送文件
	c.Data(http.StatusOK, "application/zip", zipBuffer.Bytes())
}

// 添加文件道zip中
func addFileToZip(w *zip.Writer, filename string) error {
	// 打开文件
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	// 获取文件信息
	fileInfo, err := f.Stat()
	if err != nil {
		return err
	}

	header, err := zip.FileInfoHeader(fileInfo)
	if err != nil {
		return err
	}

	// 使用文件的实际文件名
	header.Name = filepath.Base(filename)

	// 写入文件到zip
	writer, err := w.CreateHeader(header)
	if err != nil {
		return err
	}

	_, err = io.Copy(writer, f)
	if err != nil {
		return err
	}
	return err
}
