package utils

import (
	"agent-wdd/log"
	"bufio"
	"fmt"
	"io"
	"os"
	"os/user"
	"path/filepath"
	"strconv"
	"strings"
)

// AppendFileToFile 将源文件的内容添加到目标文件
func AppendFileToFile(sourceFile, targetFile string) bool {

	// 打开源文件
	source, err := os.Open(sourceFile)
	if err != nil {
		log.Error("[BasicAppendSourceToFile] - error open source file => %s, error is %s", sourceFile, err.Error())
		return false
	}
	defer source.Close()

	// 打开目标文件，如果不存在则创建，如果存在则在末尾追加
	target, err := os.OpenFile(targetFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Error("[BasicAppendSourceToFile] - error open target file => %s, error is %s", sourceFile, err.Error())
		return false
	}
	defer target.Close()

	// 将源文件内容复制到目标文件
	_, err = io.Copy(target, source)
	if err != nil {
		log.Error("[BasicAppendSourceToFile] - Error appending to target file: %s", err.Error())
		return false
	}

	return true
}

// AppendOverwriteContentToFile 向目标文件中写入一些内容,覆盖源文件
func AppendOverwriteContentToFile(content string, targetFile string) bool {

	err := os.Remove(targetFile)
	if err != nil {
		log.Warning("[BasicAppendOverwriteContentToFile] - Error removing file: %s , error is %s", targetFile, err.Error())
	}

	return AppendContentToFile(content, targetFile)
}

// AppendContentToFile 向目标文件(targetFile 文件的绝对路径)中追加写入一些内容, 如果文件不存在,那么就创建相应的目录及文件
func AppendContentToFile(content string, targetFile string) bool {

	// 创建目标文件的目录（递归创建）
	dir := filepath.Dir(targetFile)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return false
	}

	// 打开文件用于追加。如果文件不存在，将会创建一个新文件。
	file, err := os.OpenFile(targetFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Error("[BasicAppendContentToFile] - Error opening file: %s , error is %s", targetFile, err.Error())
		return false
	}
	defer file.Close() // 确保文件最终被关闭

	// 写入内容到文件
	// 内容非空时执行写入操作
	if content != "" {
		if _, err := file.WriteString(content); err != nil {
			log.Error("[BasicAppendContentToFile] - Error writing to file: %s , error is %s", targetFile, err.Error())

			return false
		}
	}

	return true
}

// AppendOverwriteListContentToFile 将一个字符串列表中的内容，一行一行的写入文件中
func AppendOverwriteListContentToFile(contentList []string, targetFile string) bool {

	err := os.Remove(targetFile)
	if err != nil {
		log.Warning("[AppendOverwriteListContentToFile] - Error removing file: %s , error is %s", targetFile, err.Error())
	}

	// 打开文件用于追加。如果文件不存在，将会创建一个新文件。
	file, err := os.OpenFile(targetFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Error("[AppendOverwriteListContentToFile] - Error opening file: %s , error is %s", targetFile, err.Error())
		return false
	}
	defer file.Close() // 确保文件最终被关闭

	// 写入内容到文件
	for _, contentLine := range contentList {
		//bytes, _ := json.Marshal(contentLine)
		if _, err := file.WriteString(contentLine + "\n"); err != nil {
			log.Error("[AppendOverwriteListContentToFile] - Error writing to file: %s , error is %s", targetFile, err.Error())
			return false
		}
	}

	return true
}

// AppendK8sYamlWithSplitLineToFile 专门为k8s的yaml文件设计的，在每次写入内容之前，先写入一行分隔符
func AppendK8sYamlWithSplitLineToFile(content string, targetFile string) bool {

	// 打开文件用于追加。如果文件不存在，将会创建一个新文件。
	file, err := os.OpenFile(targetFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Error("[BasicAppendContentToFile] - Error opening file: %s , error is %s", targetFile, err.Error())
		return false
	}
	defer file.Close() // 确保文件最终被关闭

	// 写入内容到文件
	if _, err := file.WriteString("---"); err != nil {
		log.Error("[BasicAppendContentToFile] - Error writing to file: %s , error is %s", targetFile, err.Error())
		return false
	}
	if _, err := file.WriteString(content); err != nil {
		log.Error("[BasicAppendContentToFile] - Error writing to file: %s , error is %s", targetFile, err.Error())
		return false
	}

	return true
}

// AppendNullOverWriteToFile 清空一个文件
func AppendNullOverWriteToFile(targetFile string) bool {

	// 使用os.O_TRUNC清空文件内容
	file, err := os.OpenFile(targetFile, os.O_TRUNC|os.O_WRONLY, 0644)
	if err != nil {
		log.Error("[AppendNullOverWriteToFile] - Error opening file: %s, error is %s", targetFile, err.Error())
		return false
	}
	defer file.Close() // 确保在函数退出前关闭文件

	return true
}

func WordSpaceCompletion(source string, totalLength int) string {
	sourceLength := len(source)

	if sourceLength >= totalLength {
		return source
	}

	for i := 0; i < totalLength-sourceLength; i++ {
		source += " "
	}

	return source
}

// IsDirOrFile 如果是目录则返回true，是文件则返回false
func IsDirOrFile(path string) bool {
	info, err := os.Stat(path)
	if err != nil {
		return false
	}
	return info.IsDir()
}

// FileExists 文件存在返回true，不存在返回false，如果文件是一个目录，也返回false
func FileExists(fileFullPath string) bool {
	info, err := os.Stat(fileFullPath)
	if err != nil {
		return false
	}
	return !info.IsDir()
}

// CreateFolder 创建文件夹，如果文件夹存在，则返回true，否则返回false
func CreateFolder(folderName string) bool {
	// 递归创建 类似于 mkdir -p folderName
	if _, err := os.Stat(folderName); os.IsNotExist(err) {
		return os.MkdirAll(folderName, 0755) == nil
	}
	return true
}

// FileOrFolderExists 文件或者目录是否返回true，不存在返回false
func FileOrFolderExists(fileFullPath string) bool {
	_, err := os.Stat(fileFullPath)
	return !os.IsNotExist(err)
}

// FileExistAndNotNull 文件不为空返回true 文件为空返回false
func FileExistAndNotNull(filename string) bool {

	// Check if the file exists
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		log.Debug("文件 %s 不存在！", filename)
		return false
	}

	// Open the file for reading
	file, err := os.Open(filename)
	defer file.Close()
	if err != nil {
		log.Debug("文件 %s 打开有误！", filename)
		return false // Handle error according to your needs
	}

	// Get the file size
	info, _ := file.Stat()
	size := info.Size()

	// Check if the file is not empty
	return size > 0
}

// ListAllFileInFolder 列出一个目录中的所有文件，返回文件名，忽略folder，不带全路径
func ListAllFileInFolder(folderName string) ([]string, error) {
	return listAllFileInFolderWithFullPath(folderName, false)
}

func ListAllFileInFolderWithFullPath(folderName string) ([]string, error) {
	return listAllFileInFolderWithFullPath(folderName, true)
}

func listAllFileInFolderWithFullPath(folderName string, fullPath bool) ([]string, error) {
	files := make([]string, 0)
	err := filepath.Walk(folderName, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			if fullPath {
				files = append(files, path)
			} else {
				files = append(files, info.Name())
			}
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	return files, nil
}

// RemoveFile 删除文件，如果文件不存在，则返回true
func RemoveFile(filePath string) bool {

	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		log.Error("文件不存在: %s", filePath)
		return true
	}
	err := os.Remove(filePath)
	if err != nil {
		log.Error("Failed to remove file: %s", err.Error())
		return false
	}
	return true
}

func RemoveFolderComplete(folderName string) bool {

	err := filepath.Walk(folderName,
		func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if !info.IsDir() {
				return os.Remove(path)
			}
			return nil
		})
	if err != nil {
		return false
	}
	err = os.RemoveAll(folderName)
	if err != nil {
		return false
	}
	return true
}

func ReadAllContentFromFile(fileFullPath string) (result []string) {

	f, err := os.Open(fileFullPath)
	if err != nil {
		fmt.Println(err)
		return result
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()
		if len(line) > 0 { // ignore empty lines
			result = append(result, line)
		}
	}

	if err := scanner.Err(); err != nil {
		fmt.Println(err)
		return result
	}

	return result
}

// FindContentInFile 在文件中查找内容，如果存在，则返回true，否则返回false 类似于grep -q content targetFile
func FindContentInFile(content string, targetFile string) bool {

	// 读取文件内容
	fileContent, err := os.ReadFile(targetFile)
	if err != nil {
		log.Error("[FindContentInFile] - Error reading file: %s , error is %s", targetFile, err.Error())
		return false
	}

	// 将文件内容按行分割
	lines := strings.Split(string(fileContent), "\n")

	// 遍历每一行
	for _, line := range lines {
		if strings.Contains(line, content) {
			return true
		}
	}
	return false
}

// FindAndReplaceContentInFile 在文件中查找内容，如果存在，则替换，如果存在多个，则替换全部 类似于sed -i 's/oldContent/newContent/g' targetFile
func FindAndReplaceContentInFile(oldContent string, newContent string, targetFile string) bool {

	// 读取文件内容
	fileContent, err := os.ReadFile(targetFile)
	if err != nil {
		log.Error("[FindAndReplaceContentInFile] - Error reading file: %s , error is %s", targetFile, err.Error())
		return false
	}

	// 将文件内容按行分割
	lines := strings.Split(string(fileContent), "\n")

	// 遍历每一行
	for i, line := range lines {
		if strings.Contains(line, oldContent) {
			lines[i] = strings.Replace(line, oldContent, newContent, -1)
		}
	}

	// 将修改后的内容写回文件
	err = os.WriteFile(targetFile, []byte(strings.Join(lines, "\n")), 0644)
	if err != nil {
		log.Error("[FindAndReplaceContentInFile] - Error writing file: %s , error is %s", targetFile, err.Error())
		return false
	}

	return true
}

// FindAndDeleteContentInFile 在文件中查找内容，如果存在，则删除，如果存在多个，则删除全部 类似于sed -i '/content/d' targetFile
func FindAndDeleteContentInFile(content string, targetFile string) bool {

	// 读取文件内容
	fileContent, err := os.ReadFile(targetFile)
	if err != nil {
		log.Error("[FindAndDeleteContentInFile] - Error reading file: %s , error is %s", targetFile, err.Error())
		return false
	}

	// 将文件内容按行分割
	lines := strings.Split(string(fileContent), "\n")

	// 过滤掉包含指定内容的行
	var newLines []string
	for _, line := range lines {
		if !strings.Contains(line, content) {
			newLines = append(newLines, line)
		}
	}

	// 将过滤后的内容写回文件
	err = os.WriteFile(targetFile, []byte(strings.Join(newLines, "\n")), 0644)
	if err != nil {
		log.Error("[FindAndDeleteContentInFile] - Error writing file: %s , error is %s", targetFile, err.Error())
		return false
	}

	return true
}

// MoveFileToAnother 将源文件移动到目标文件
func MoveFileToAnother(srcFile, dstFile string) error {

	// 如果dstFile是目录，则将srcFile移动到dstFile目录下
	if IsDirOrFile(dstFile) {
		dstFile = filepath.Join(dstFile, filepath.Base(srcFile))
	}

	// 如果目标文件存在，则删除目标文件
	if FileExists(dstFile) {
		err := os.Remove(dstFile)
		if err != nil {
			return fmt.Errorf("删除目标文件失败: %w", err)
		}
	}

	// 如果源文件不存在，则返回错误
	if !FileExists(srcFile) {
		return fmt.Errorf("源文件不存在: %s", srcFile)
	}

	// 如果目标文件夹不存在，则创建目标文件夹
	if !FileExists(filepath.Dir(dstFile)) {
		err := os.MkdirAll(filepath.Dir(dstFile), os.ModePerm)
		if err != nil {
			return fmt.Errorf("创建目标文件夹失败: %w", err)
		}
	}

	// 移动文件
	return os.Rename(srcFile, dstFile)
}

// MoveFolerToAnother 将源文件夹的所有文件递归移动到目标文件夹
func MoveFolerToAnother(srcDir, dstDir string) error {
	// 读取源文件夹中的所有条目
	entries, err := os.ReadDir(srcDir)
	if err != nil {
		return fmt.Errorf("读取源文件夹失败: %w", err)
	}

	// 创建目标文件夹（如果不存在）
	if err := os.MkdirAll(dstDir, os.ModePerm); err != nil {
		return fmt.Errorf("创建目标文件夹失败: %w", err)
	}

	// 遍历所有条目
	for _, entry := range entries {
		srcPath := filepath.Join(srcDir, entry.Name())
		dstPath := filepath.Join(dstDir, entry.Name())

		// 如果是文件夹，递归处理
		if entry.IsDir() {
			if err := MoveFolerToAnother(srcPath, dstPath); err != nil {
				return fmt.Errorf("递归移动文件夹失败: %w", err)
			}
		} else {
			// 移动文件
			if err := os.Rename(srcPath, dstPath); err != nil {
				return fmt.Errorf("移动文件失败: %w", err)
			}
		}
	}

	// 删除源文件夹
	if err := os.RemoveAll(srcDir); err != nil {
		return fmt.Errorf("删除源文件夹失败: %w", err)
	}

	return nil

}

// GetCurrentUserFolder 获取运行环境当前用户的根目录
func GetCurrentUserFolder() string {
	usr, err := user.Current()
	if err != nil {
		fmt.Println(err)
		return ""
	}

	return usr.HomeDir
}

// PermissionFile 设置文件权限
func permissionFile(filePath string, permission string) error {
	// 将字符串权限转换为 FileMode
	perm, err := strconv.ParseUint(permission, 8, 32)
	if err != nil {
		return fmt.Errorf("权限格式无效: %w", err)
	}
	return os.Chmod(filePath, os.FileMode(perm))
}

// PermissionFileExecute 设置文件可执行权限
func PermissionFileExecute(filePath string) error {
	return permissionFile(filePath, "0777")
}

// PermissionFileRead 设置文件可读权限
func PermissionFileRead(filePath string) error {
	return permissionFile(filePath, "0644")
}

// PermissionFileWrite 设置文件可写权限
func PermissionFileWrite(filePath string) error {
	return permissionFile(filePath, "0666")
}
