package utils

import (
	"agent-wdd/log"
	"archive/tar"
	"archive/zip"
	"compress/gzip"
	"io"
	"os"
	"path/filepath"
)

// UnzipFile 解压文件, 支持zip tgz tar.gz tar
func UnzipFile(zipFile string, targetFolder string) {
	log.Info("解压文件: %s, 到: %s", zipFile, targetFolder)

	// 检查文件扩展名以确定解压缩方法
	fileExt := filepath.Ext(zipFile)
	switch fileExt {
	case ".zip":
		// 使用标准库中的archive/zip包进行解压缩
		zipReader, err := zip.OpenReader(zipFile)
		if err != nil {
			log.Error("无法打开ZIP文件: %s, 错误: %s", zipFile, err.Error())
			return
		}
		defer zipReader.Close()

		// 创建目标文件夹
		if err := os.MkdirAll(targetFolder, 0755); err != nil {
			log.Error("无法创建目标文件夹: %s, 错误: %s", targetFolder, err.Error())
			return
		}

		// 遍历ZIP文件中的所有文件
		for _, file := range zipReader.File {
			zippedFile, err := file.Open()
			if err != nil {
				log.Error("无法打开ZIP中的文件: %s, 错误: %s", file.Name, err.Error())
				continue
			}
			defer zippedFile.Close()

			// 构建目标文件路径
			targetFilePath := filepath.Join(targetFolder, file.Name)

			// 如果是目录，则创建目录
			if file.FileInfo().IsDir() {
				if err := os.MkdirAll(targetFilePath, file.Mode()); err != nil {
					log.Error("无法创建目录: %s, 错误: %s", targetFilePath, err.Error())
					continue
				}
			} else {
				// 如果是文件，则创建文件并写入内容
				if err := os.MkdirAll(filepath.Dir(targetFilePath), 0755); err != nil {
					log.Error("无法创建文件的父目录: %s, 错误: %s", filepath.Dir(targetFilePath), err.Error())
					continue
				}
				targetFile, err := os.OpenFile(targetFilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
				if err != nil {
					log.Error("无法创建目标文件: %s, 错误: %s", targetFilePath, err.Error())
					continue
				}
				defer targetFile.Close()

				if _, err := io.Copy(targetFile, zippedFile); err != nil {
					log.Error("无法写入文件内容: %s, 错误: %s", targetFilePath, err.Error())
					continue
				}
			}
		}

	case ".tar", ".tar.gz", ".tgz":
		// 使用标准库中的archive/tar包进行解压缩
		var file *os.File
		var err error
		if fileExt == ".tar.gz" || fileExt == ".tgz" {
			file, err = os.Open(zipFile)
			if err != nil {
				log.Error("无法打开TAR.GZ文件: %s, 错误: %s", zipFile, err.Error())
				return
			}
			defer file.Close()

			gzipReader, err := gzip.NewReader(file)
			if err != nil {
				log.Error("无法创建GZIP读取器: %s, 错误: %s", zipFile, err.Error())
				return
			}
			defer gzipReader.Close()

			tarReader := tar.NewReader(gzipReader)
			if err := extractTar(tarReader, targetFolder); err != nil {
				log.Error("解压TAR.GZ文件时出错: %s, 错误: %s", zipFile, err.Error())
				return
			}
		} else {
			file, err = os.Open(zipFile)
			if err != nil {
				log.Error("无法打开TAR文件: %s, 错误: %s", zipFile, err.Error())
				return
			}
			defer file.Close()

			tarReader := tar.NewReader(file)
			if err := extractTar(tarReader, targetFolder); err != nil {
				log.Error("解压TAR文件时出错: %s, 错误: %s", zipFile, err.Error())
				return
			}
		}

	default:
		log.Error("不支持的文件类型: %s", fileExt)
		return
	}
}

// 辅助函数，用于解压TAR文件
func extractTar(tarReader *tar.Reader, targetFolder string) error {
	for {
		header, err := tarReader.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}

		targetFilePath := filepath.Join(targetFolder, header.Name)

		switch header.Typeflag {
		case tar.TypeDir:
			if err := os.MkdirAll(targetFilePath, 0755); err != nil {
				return err
			}
		case tar.TypeReg:
			if err := os.MkdirAll(filepath.Dir(targetFilePath), 0755); err != nil {
				return err
			}
			file, err := os.OpenFile(targetFilePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, os.FileMode(header.Mode))
			if err != nil {
				return err
			}
			defer file.Close()

			if _, err := io.Copy(file, tarReader); err != nil {
				return err
			}
		}
	}
	return nil
}
