package files

import (
	"encoding/base64"
	"fmt"
	"godo/libs"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"sync"
)

// 全局变量来存储 key 和 path 的映射关系
var OnlyOfficekeyPathMap = make(map[string]string)
var mapOnlyOfficeMutex sync.Mutex

func HandleReadFile(w http.ResponseWriter, r *http.Request) {
	path := r.URL.Query().Get("path")
	//log.Printf("read file: %s", path)
	if path == "" {
		libs.ErrorMsg(w, "文件路径不能为空")
		return
	}
	stream := r.URL.Query().Get("stream")
	isStream := false
	if stream != "" {
		isStream = true
		mapOnlyOfficeMutex.Lock()
		OnlyOfficekeyPathMap[stream] = path
		mapOnlyOfficeMutex.Unlock()
	}

	basePath, err := libs.GetOsDir()
	if err != nil {
		libs.ErrorMsg(w, err.Error())
		return
	}
	fullFilePath := filepath.Join(basePath, path)
	file, err := os.Open(fullFilePath)
	if err != nil {
		libs.ErrorMsg(w, err.Error())
		return
	}
	fileData, err := io.ReadAll(file)
	if err != nil {
		libs.ErrorMsg(w, err.Error())
		return
	}
	text := string(fileData)
	//log.Printf("isPwd: %v", strData)
	if strings.HasPrefix(text, "link::") {
		libs.SuccessMsg(w, text, "文件读取成功")
		return
	}
	// 判断是否为加密文件
	isPwd := libs.IsEncryptedFile(text)

	if !isPwd {
		// 未加密文件,直接返回

		if isStream {
			w.Header().Set("Content-Type", "application/octet-stream")
			_, err := w.Write(fileData)
			if err != nil {
				libs.ErrorMsg(w, err.Error())
				return
			}
		} else {
			if len(fileData) > 0 {
				text = base64.StdEncoding.EncodeToString(fileData)
			}
			//text = base64.StdEncoding.EncodeToString(fileData)
			libs.SuccessMsg(w, text, "文件读取成功")
		}

		return
	}
	filePwd := r.Header.Get("pwd")
	// 获取文件密钥
	fileSecret := libs.GetConfigString("filePwd")
	if filePwd == "" && fileSecret == "" {
		libs.Error(w, "加密文件,需要密码", "needPwd")
		return
	}
	decodeFile := ""
	needPwd := false
	if fileSecret != "" {
		decodeFile, err = libs.DecodeFile(fileSecret, text)
		if err != nil {
			libs.Error(w, "请输入文件密码", "needPwd")
			return
		}
		needPwd = true
	}
	if filePwd != "" && !needPwd {
		decodeFile, err = libs.DecodeFile(filePwd, text)
		if err != nil {
			libs.Error(w, "文件密码输入错误", "needPwd")
			return
		}
	}
	if isStream {
		w.Header().Set("Content-Type", "application/octet-stream")
		_, err := w.Write([]byte(decodeFile))
		if err != nil {
			libs.ErrorMsg(w, err.Error())
			return
		}
	} else {
		if len(decodeFile) > 0 {
			decodeFile = base64.StdEncoding.EncodeToString([]byte(decodeFile))
		}
		libs.SuccessMsg(w, decodeFile, "加密文件读取成功")
	}

}
func HandleWriteFile(w http.ResponseWriter, r *http.Request) {

	path := r.URL.Query().Get("path")
	if err := validateFilePath(path); err != nil {
		libs.HTTPError(w, http.StatusBadRequest, err.Error())
		return
	}
	basePath, err := libs.GetOsDir()
	if err != nil {
		libs.HTTPError(w, http.StatusInternalServerError, err.Error())
		return
	}
	fullFilePath := filepath.Join(basePath, path)
	//  获取文件内容
	fileContent, _, err := r.FormFile("content")
	if err != nil {
		libs.HTTPError(w, http.StatusBadRequest, err.Error())
		return
	}
	defer fileContent.Close()
	content, err := io.ReadAll(fileContent)
	if err != nil {
		libs.HTTPError(w, http.StatusInternalServerError, err.Error())
		return
	}
	// 打开文件,如果不存在则创建
	file, err := os.OpenFile(fullFilePath, os.O_RDWR|os.O_CREATE, 0644)
	if err != nil {
		libs.ErrorMsg(w, "Failed to create file.")
		return
	}
	defer file.Close()

	oldContent, err := io.ReadAll(file)
	text := string(oldContent)
	//log.Printf("text: %s", text)
	if err != nil {
		libs.ErrorMsg(w, err.Error())
		return
	}
	isPwdFile := libs.IsEncryptedFile(text)

	filePwd := r.Header.Get("pwd")
	// 获取文件密钥
	fileSecret := libs.GetConfigString("filePwd")
	haslink := strings.HasPrefix(string(content), "link::")
	//log.Printf("haslink:%v,fileSecret: %s,isPwdFile:%v,filePwd:%s", haslink, fileSecret, isPwdFile, filePwd)
	needPwd := false

	if fileSecret != "" || filePwd != "" {
		needPwd = true
	}
	if isPwdFile {
		needPwd = true
	}
	if haslink {
		needPwd = false
	}
	//log.Printf("needPwd:%v", needPwd)
	// 即不是加密用户又不是加密文件
	if !needPwd {
		// 直接写入新内容
		file.Truncate(0)
		file.Seek(0, 0)
		//log.Printf("write file content%v", content)
		_, err = file.Write(content)
		if err != nil {
			libs.ErrorMsg(w, "Failed to write file content.")
			return
		}
		CheckAddDesktop(path)
		libs.SuccessMsg(w, "", "文件写入成功")
		return
	}

	//log.Printf("fileSecret:%s,filePwd:%s,ispwdfile:%v", fileSecret, filePwd, isPwdFile)

	// 是加密文件,写入需继续加密
	pwd := ""
	if isPwdFile {
		//先尝试系统解密
		if fileSecret != "" {
			_, err := libs.DecodeFile(fileSecret, text)
			if err == nil {
				pwd = fileSecret
			}
		}
		//先用户输入解密
		if pwd == "" && filePwd != "" {
			_, err := libs.DecodeFile(filePwd, text)
			if err == nil {
				pwd = filePwd
			}
		}

	} else {
		// 不是加密文件,先判断是否有用户输入
		if filePwd != "" {
			pwd = filePwd
		} else {
			// 没有用户输入,则使用系统默认密码
			if fileSecret != "" {
				pwd = fileSecret
			}
		}
	}
	if pwd == "" {
		libs.Error(w, "文件密码错误", "needPwd")
		//log.Printf("pwd is empty, returning error")
		return
	}
	//log.Printf("pwd: %s", pwd)

	encryData, err := libs.EncodeFile(pwd, string(content))
	if err != nil {
		libs.ErrorMsg(w, err.Error())
		return
	}

	// 清空文件内容
	file.Truncate(0)
	file.Seek(0, 0)

	_, err = file.Write([]byte(encryData))
	if err != nil {
		libs.ErrorMsg(w, fmt.Sprintf("文件内容写入失败: %s", err.Error()))
		return
	}
	CheckAddDesktop(path)
	libs.SuccessMsg(w, "", "文件写入成功")
}

func HandleSetFilePwd(w http.ResponseWriter, r *http.Request) {
	Pwd := r.Header.Get("Pwd")
	if Pwd == "" {
		err := libs.DeleteConfig("filePwd")
		if err != nil {
			libs.ErrorMsg(w, fmt.Sprintf("取消加密失败:%s", err.Error()))
			return
		}
		libs.SuccessMsg(w, nil, "取消加密成功")
		return
	}
	err := libs.SetConfigByName("filePwd", Pwd)
	if err != nil {
		libs.ErrorMsg(w, err.Error())
		return
	}
	libs.SuccessMsg(w, nil, "设置密码成功")
}