package filesystem

import (
	"archive/zip"
	"fmt"
	"io"
	"path/filepath"
)

// ZipOperation ZIP操作回调函数类型
// 用于 withZipReader 通用包装器
type ZipOperation func(*zip.ReadCloser) (interface{}, error)

// withZipReader 通用的ZIP文件操作包装器
// 消除重复的打开/关闭逻辑，统一错误处理
// 参数:
//   - zipPath: ZIP文件路径
//   - operation: 操作回调函数，接收 *zip.ReadCloser，返回任意结果
//
// 返回:
//   - interface{}: 操作结果
//   - error: 错误信息
func withZipReader(zipPath string, operation ZipOperation) (interface{}, error) {
	// 1. 统一验证路径
	if err := validateZipPath(zipPath); err != nil {
		return nil, err
	}

	// 2. 打开 ZIP 文件
	reader, err := zip.OpenReader(zipPath)
	if err != nil {
		return nil, fmt.Errorf("打开 zip 文件失败: %v", err)
	}
	defer reader.Close()

	// 3. 执行操作
	result, err := operation(reader)
	if err != nil {
		return nil, err
	}

	return result, nil
}

// withZipFile 在ZIP文件中查找特定文件并执行操作
// 进一步封装，用于处理单个文件的操作
type ZipFileOperation func(*zip.File) (interface{}, error)

// withZipFile 在ZIP中查找文件并执行操作
func withZipFile(zipPath, filePath string, operation ZipFileOperation) (interface{}, error) {
	return withZipReader(zipPath, func(reader *zip.ReadCloser) (interface{}, error) {
		// 查找目标文件
		for _, file := range reader.File {
			if isMatchFile(file, filePath) {
				return operation(file)
			}
		}
		return nil, fmt.Errorf("文件在 zip 中不存在: %s", filePath)
	})
}

// isMatchFile 检查文件是否匹配目标路径
func isMatchFile(file *zip.File, targetPath string) bool {
	return file.Name == targetPath ||
	       filepath.Clean(file.Name) == filepath.Clean(targetPath)
}

// readAllFromFile 从文件读取所有内容
// 辅助函数，避免重复的 io.ReadAll 调用
func readAllFromFile(rc io.ReadCloser) ([]byte, error) {
	defer rc.Close()
	return io.ReadAll(rc)
}

// getCompressionMethodString 获取压缩方法字符串描述
func getCompressionMethodString(method uint16) string {
	if method == 8 {
		return "Deflate"
	}
	return "Store"
}

// createFileInfoMap 创建文件信息map（通用格式）
func createFileInfoMap(file *zip.File, includeExtra ...bool) map[string]interface{} {
	info := map[string]interface{}{
		"name":       filepath.Base(file.Name),
		"path":       file.Name, // zip 中的路径（已使用 /）
		"is_dir":     file.Mode().IsDir(),
		"size":       file.UncompressedSize64,
		"compressed": file.CompressedSize64,
		"mod_time":   file.Modified.Format("2006-01-02 15:04:05"),
		"method":     getCompressionMethodString(file.Method),
	}

	// 可选：额外信息
	if len(includeExtra) > 0 && includeExtra[0] {
		info["mode"] = file.Mode().String()
		info["comment"] = file.Comment
	}

	return info
}
