//go:build windows
// +build windows

package filesystem

import (
	"fmt"
	"os"
	"syscall"
)

// FileLockChecker 文件锁检查器
type FileLockChecker struct{}

// NewFileLockChecker 创建文件锁检查器
func NewFileLockChecker() *FileLockChecker {
	return &FileLockChecker{}
}

// IsFileLocked 检查文件是否被锁定（被其他进程占用）
// 返回: (是否锁定, 错误信息, 错误)
func (c *FileLockChecker) IsFileLocked(path string) (bool, string, error) {
	// 尝试以独占写模式打开文件
	file, err := os.OpenFile(path, os.O_RDWR|syscall.O_CREAT, 0666)
	if err != nil {
		// 检查是否是锁相关的错误
		if isLockError(err) {
			// 获取占用该文件的进程信息
			processInfo, _ := c.getProcessInfo(path)
			return true, processInfo, nil
		}
		return false, "", err
	}
	defer file.Close()

	// 文件可以被打开，说明没有被锁定
	return false, "", nil
}

// isLockError 判断错误是否为文件锁定错误
func isLockError(err error) bool {
	if err == nil {
		return false
	}

	// 检查错误类型
	if os.IsPermission(err) {
		return true
	}

	// Windows 特定错误检查
	if pathErr, ok := err.(*os.PathError); ok {
		errno, ok := pathErr.Err.(syscall.Errno)
		if ok && (errno == ERROR_SHARING_VIOLATION ||
			errno == ERROR_LOCK_VIOLATION ||
			errno == syscall.ERROR_ACCESS_DENIED) {
			return true
		}
	}

	errStr := err.Error()
	lockErrorStrings := []string{
		"used by another process",
		"being used",
		"access is denied",
		"could not be opened",
		"being used by another process",
		"process cannot access the file",
		"used by another process",
	}

	for _, lockStr := range lockErrorStrings {
		if contains(errStr, lockStr) {
			return true
		}
	}

	return false
}

// getProcessInfo 获取占用文件的进程信息（Windows专用）
func (c *FileLockChecker) getProcessInfo(path string) (string, error) {
	// 在Windows上，使用重启管理器API查询文件占用
	// 这里提供简化版本

	// 尝试打开文件获取更多信息
	handle, err := syscall.Open(path, syscall.O_RDONLY, 0)
	if err != nil {
		// 如果打开失败，返回通用提示
		return "", nil
	}
	defer syscall.Close(handle)

	// 使用 Windows API 查询文件信息
	// 注意：这需要更复杂的 Windows API 调用
	// 这里返回简化的提示信息
	return "文件正被其他程序使用", nil
}

// SafeDeleteWithLockCheck 带锁检查的安全删除
func (c *FileLockChecker) SafeDeleteWithLockCheck(path string) error {
	// 检查文件是否被锁定
	locked, processInfo, err := c.IsFileLocked(path)
	if err != nil && !locked {
		return err
	}

	if locked {
		if processInfo != "" {
			return fmt.Errorf("无法删除文件：文件正被其他程序使用\n\n提示：%s\n\n请关闭相关程序后重试", processInfo)
		}
		return fmt.Errorf("无法删除文件：文件正被其他程序使用\n\n请关闭相关程序后重试")
	}

	// 文件未被锁定，继续删除
	return nil
}

// Windows 特定的结构体和常量
const (
	ERROR_LOCK_VIOLATION    = 33 // syscall.Errno(33)
	ERROR_SHARING_VIOLATION = 32 // syscall.Errno(32)
)

// contains 检查字符串是否包含子串（不区分大小写）
func contains(str, substr string) bool {
	return len(str) >= len(substr) && (str == substr || len(substr) == 0 ||
		(len(str) > 0 && len(substr) > 0 && containsIgnoreCase(str, substr)))
}

func containsIgnoreCase(str, substr string) bool {
	// 简化版小写比较
	for i := 0; i <= len(str)-len(substr); i++ {
		match := true
		for j := 0; j < len(substr); j++ {
			c1 := str[i+j]
			c2 := substr[j]
			if c1 >= 'A' && c1 <= 'Z' {
				c1 += 32
			}
			if c2 >= 'A' && c2 <= 'Z' {
				c2 += 32
			}
			if c1 != c2 {
				match = false
				break
			}
		}
		if match {
			return true
		}
	}
	return false
}

