package filesystem

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
)

// PathValidator 路径验证器接口
// 提供统一的路径安全检查，避免重复代码
type PathValidator interface {
	// Validate 验证路径并返回详细的错误信息
	Validate(path string) *ValidationError

	// IsSafe 快速检查路径是否安全
	IsSafe(path string) bool

	// IsSensitive 检查路径是否为敏感路径
	IsSensitive(path string) bool
}

// ValidationError 验证错误
type ValidationError struct {
	Path    string
	Reason  string
	IsError bool // true=禁止访问, false=敏感路径
}

func (e *ValidationError) Error() string {
	if e.IsError {
		return fmt.Sprintf("路径验证失败: %s - %s", e.Path, e.Reason)
	}
	return fmt.Sprintf("敏感路径警告: %s - %s", e.Path, e.Reason)
}

// DefaultPathValidator 默认路径验证器实现
type DefaultPathValidator struct {
	config *Config
}

// NewPathValidator 创建新的路径验证器
func NewPathValidator(config *Config) PathValidator {
	return &DefaultPathValidator{
		config: config,
	}
}

// Validate 验证路径
func (v *DefaultPathValidator) Validate(path string) *ValidationError {
	// 清理路径
	cleanPath := filepath.Clean(path)

	// 1. 检查路径遍历攻击
	if strings.Contains(cleanPath, PathTraversalPattern) {
		return &ValidationError{
			Path:    path,
			Reason:  "检测到路径遍历尝试",
			IsError: true,
		}
	}

	// 2. 检查符号链接
	if !v.config.Security.PathValidation.AllowSymlinks {
		if fi, err := os.Lstat(path); err == nil && fi.Mode()&os.ModeSymlink != 0 {
			return &ValidationError{
				Path:    path,
				Reason:  "不允许访问符号链接",
				IsError: true,
			}
		}
	}

	// 3. 检查UNC路径（Windows）
	if runtime.GOOS == "windows" && !v.config.Security.PathValidation.AllowUNCPaths {
		if strings.HasPrefix(cleanPath, `\\`) {
			return &ValidationError{
				Path:    path,
				Reason:  "不允许访问UNC网络路径",
				IsError: true,
			}
		}
	}

	// 4. Windows特定检查
	if runtime.GOOS == "windows" && v.config.Security.PathValidation.CheckWindowsSystemPaths {
		if err := v.checkWindowsSystemPaths(cleanPath); err != nil {
			return err
		}
	}

	// 5. 检查敏感路径
	if v.isSensitivePath(cleanPath) {
		return &ValidationError{
			Path:    path,
			Reason:  "访问敏感路径",
			IsError: false, // 警告而非错误
		}
	}

	return nil
}

// IsSafe 快速检查路径是否安全
func (v *DefaultPathValidator) IsSafe(path string) bool {
	err := v.Validate(path)
	return err == nil || !err.IsError
}

// IsSensitive 检查路径是否为敏感路径
func (v *DefaultPathValidator) IsSensitive(path string) bool {
	cleanPath := filepath.Clean(path)
	return v.isSensitivePath(cleanPath)
}

// checkWindowsSystemPaths 检查Windows系统路径
func (v *DefaultPathValidator) checkWindowsSystemPaths(path string) *ValidationError {
	lowerPath := strings.ToLower(path)

	// 检查盘符
	if len(lowerPath) >= 3 && lowerPath[1] == ':' {
		driveLetter := lowerPath[0:1]

		// 检查系统关键目录（仅保留最关键的系统目录）
		forbiddenDirs := []string{
			driveLetter + ":\\windows",
			driveLetter + ":\\program files",
			driveLetter + ":\\program files (x86)",
			driveLetter + ":\\program files (arm)",
			driveLetter + ":\\system volume information",
			driveLetter + ":\\boot",
		}

		for _, fb := range forbiddenDirs {
			if strings.HasPrefix(lowerPath, fb) {
				return &ValidationError{
					Path:    path,
					Reason:  "禁止访问系统关键目录",
					IsError: true,
				}
			}
		}

		// 检查用户配置目录（可能包含敏感信息）
		forbiddenPaths := []string{
			"\\.ssh\\",
			"\\.gnupg\\",
			"\\.config\\",
			"\\appdata\\roaming\\mozilla\\",
			"\\appdata\\roaming\\google\\chrome\\",
			"\\appdata\\local\\google\\user data\\",
		}

		for _, fp := range forbiddenPaths {
			if strings.Contains(lowerPath, fp) {
				return &ValidationError{
					Path:    path,
					Reason:  "禁止访问敏感配置目录",
					IsError: true,
				}
			}
		}
	}

	return nil
}

// isSensitivePath 检查是否为敏感路径
func (v *DefaultPathValidator) isSensitivePath(path string) bool {
	lowerPath := strings.ToLower(filepath.Clean(path))

	// 检查配置的敏感路径列表
	for _, sp := range v.config.Security.PathValidation.SensitivePaths {
		if strings.Contains(lowerPath, strings.ToLower(sp)) {
			return true
		}
	}

	return false
}

// 默认路径验证器（缓存，避免每次调用重复初始化）
var (
	defaultValidatorOnce sync.Once
	defaultValidator     PathValidator
)

func getDefaultValidator() PathValidator {
	defaultValidatorOnce.Do(func() {
		defaultValidator = NewPathValidator(DefaultConfig())
	})
	return defaultValidator
}

// isSafePath 兼容函数：保持向后兼容
func isSafePath(path string) bool {
	return getDefaultValidator().IsSafe(path)
}

// isSensitivePath 兼容函数：保持向后兼容
func isSensitivePath(path string) bool {
	return getDefaultValidator().IsSensitive(path)
}
