package filesystem

import (
	"context"
	"encoding/base64"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"time"

	"u-desk/internal/common"
)

const maxReadWriteSize = 10 * 1024 * 1024 // 10MB 读写上限

// FileOperationResult 文件操作结果
type FileOperationResult struct {
	Path      string `json:"path"`
	Name      string `json:"name"`
	Size      int64  `json:"size"`
	SizeStr   string `json:"size_str,omitempty"`
	IsDir     bool   `json:"is_dir"`
	ModTime   string `json:"mod_time,omitempty"`
	Mode      string `json:"mode,omitempty"`
	OldPath   string `json:"old_path,omitempty"` // 仅重命名操作时有值
	Deleted   bool   `json:"deleted,omitempty"`   // 仅删除操作时有值
}

// FileSystemService 文件系统服务
// 统一管理所有文件系统相关的功能，使用依赖注入而非全局变量
type FileSystemService struct {
	// 核心组件
	config         *Config
	pathValidator  PathValidator
	fileTypeManager FileTypeManager

	// 基础设施组件
	auditLogger   *AuditLogger
	recycleBin    *RecycleBin
	lockChecker   *FileLockChecker

	// 状态管理
	mu             sync.RWMutex
	initialized   bool
}

// NewFileSystemService 创建新的文件系统服务
// 使用依赖注入，所有组件通过参数传入，便于测试和替换
func NewFileSystemService(config *Config) (*FileSystemService, error) {
	if config == nil {
		config = DefaultConfig()
	}

	service := &FileSystemService{
		config:        config,
		pathValidator: NewPathValidator(config),
		fileTypeManager: NewFileTypeManager(config),
	}

	// 初始化基础设施组件
	if err := service.initializeComponents(); err != nil {
		return nil, fmt.Errorf("初始化文件系统服务失败: %w", err)
	}

	service.initialized = true
	return service, nil
}

// initializeComponents 初始化各个组件
func (s *FileSystemService) initializeComponents() error {
	// 1. 初始化审计日志
	if s.config.Features.AuditLog {
		if err := s.initAuditLogger(); err != nil {
			return fmt.Errorf("初始化审计日志失败: %w", err)
		}
	}

	// 2. 初始化回收站
	if s.config.Features.RecycleBin {
		if err := s.initRecycleBin(); err != nil {
			return fmt.Errorf("初始化回收站失败: %w", err)
		}
	}

	// 3. 初始化文件锁检查器
	if s.config.Features.FileLockCheck {
		s.lockChecker = NewFileLockChecker()
	}

	return nil
}

// initAuditLogger 初始化审计日志
func (s *FileSystemService) initAuditLogger() error {
	logDir := filepath.Join(common.GetUserDataDir(), "logs")
	logger, err := NewAuditLogger(logDir)
	if err != nil {
		return err
	}
	s.auditLogger = logger
	return nil
}

// initRecycleBin 初始化回收站
func (s *FileSystemService) initRecycleBin() error {
	recycleBinPath := filepath.Join(common.GetUserDataDir(), "recycle_bin")
	bin, err := NewRecycleBin(recycleBinPath)
	if err != nil {
		return err
	}
	s.recycleBin = bin
	return nil
}

// ========== 核心文件操作 ==========

// ReadFile 读取文件内容（限制最大 10MB）
func (s *FileSystemService) ReadFile(path string) (string, error) {
	// 路径验证
	if err := s.validatePath(path); err != nil {
		return "", err
	}

	// 检查文件大小，避免读取超大文件导致内存问题
	info, err := os.Stat(path)
	if err != nil {
		return "", fmt.Errorf("获取文件信息失败: %v", err)
	}
	if info.Size() > maxReadWriteSize {
		return "", fmt.Errorf("文件过大 (%.1f MB)，超过读取上限 (%d MB)", float64(info.Size())/1024/1024, maxReadWriteSize/1024/1024)
	}

	// 读取文件
	data, err := os.ReadFile(path)
	if err != nil {
		return "", fmt.Errorf("读取文件失败: %v", err)
	}

	s.logRead(path, int64(len(data)), nil)
	return string(data), nil
}

// Write 写入文件内容（实现 FileService 接口)
// writeFile 内部写入实现（路径验证+大小检查+写入+日志）
func (s *FileSystemService) writeFileWithLog(path string, data []byte) error {
	if err := s.validatePath(path); err != nil {
		return err
	}
	dir := filepath.Dir(path)
	if err := os.MkdirAll(dir, DefaultDirPermissions); err != nil {
		return fmt.Errorf("创建目录失败: %v", err)
	}
	if len(data) > maxReadWriteSize {
		return fmt.Errorf("文件过大 (%.1f MB)，超过写入上限 (%d MB)", float64(len(data))/1024/1024, maxReadWriteSize/1024/1024)
	}
	if err := os.WriteFile(path, data, DefaultFilePermissions); err != nil {
		s.logWrite(path, int64(len(data)), err)
		return fmt.Errorf("写入文件失败: %v", err)
	}
	s.logWrite(path, int64(len(data)), nil)
	return nil
}

// WriteFile 写入文件
func (s *FileSystemService) WriteFile(path, content string) error {
	return s.writeFileWithLog(path, []byte(content))
}

// SaveBase64File 将 base64 编码内容解码后写入二进制文件
func (s *FileSystemService) SaveBase64File(path, base64Content string) error {
	if strings.TrimSpace(base64Content) == "" {
		return errors.New("base64 内容不能为空")
	}
	data, err := base64.StdEncoding.DecodeString(base64Content)
	if err != nil {
		return fmt.Errorf("base64 解码失败: %v", err)
	}
	return s.writeFileWithLog(path, data)
}

// DeletePath 删除文件或目录
func (s *FileSystemService) DeletePath(path string) (*FileOperationResult, error) {
	return s.DeletePathWithContext(context.Background(), path)
}

// DeletePathWithContext 带上下文的删除操作，返回被删除文件的信息
func (s *FileSystemService) DeletePathWithContext(ctx context.Context, path string) (*FileOperationResult, error) {
	// 路径验证
	if err := s.validatePath(path); err != nil {
		return nil, err
	}

	// 获取文件信息（在删除前保存）
	info, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, fmt.Errorf("文件或目录不存在")
		}
		return nil, fmt.Errorf("获取文件信息失败: %v", err)
	}

	// 检查删除限制
	exceeds, details, checkErr := CheckDeleteRestrictions(path, info, s.config)
	if checkErr != nil {
		return nil, checkErr
	}

	if exceeds {
		if s.config.Security.DeleteRestrictions.RequireConfirm {
			return nil, &DeleteRestrictionWarning{
				Path:    path,
				Details: details,
				Info:    info,
			}
		}
		return nil, fmt.Errorf("删除限制: %s", details)
	}

	// 文件锁检查（可选）
	if s.lockChecker != nil {
		if err := s.lockChecker.SafeDeleteWithLockCheck(path); err != nil {
			return nil, err
		}
	}

	// 执行删除
	var deleteErr error
	if info.IsDir() {
		deleteErr = os.RemoveAll(path)
	} else {
		deleteErr = os.Remove(path)
	}

	s.logDelete(path, info.IsDir(), info.Size(), deleteErr)

	if deleteErr != nil {
		return nil, fmt.Errorf("删除失败: %v", deleteErr)
	}

	// 如果启用回收站，移动到回收站而非永久删除
	if s.recycleBin != nil {
		// 检查是否已在回收站中
		if !isInRecycleBin(path) {
			if err := s.recycleBin.MoveToRecycleBin(path); err != nil {
				// 回收站失败，记录但继续
				fmt.Printf("[警告] 移动到回收站失败: %v\n", err)
			}
		}
	}

	// 返回被删除的文件信息，用于前端更新
	return &FileOperationResult{
		Path:     filepath.ToSlash(path), // 统一使用正斜杠
		Name:     info.Name(),
		Size:     info.Size(),
		SizeStr:  FormatBytes(info.Size()),
		IsDir:    info.IsDir(),
		ModTime:  info.ModTime().Format("2006-01-02 15:04:05"),
		Mode:     info.Mode().String(),
		Deleted:  true,
	}, nil
}

// ListDir 列出目录内容
func (s *FileSystemService) ListDir(path string) ([]map[string]interface{}, error) {
	// 路径验证
	if err := s.validatePath(path); err != nil {
		return nil, err
	}

	// 读取目录
	entries, err := os.ReadDir(path)
	if err != nil {
		return nil, fmt.Errorf("读取目录失败: %v", err)
	}

	// 转换为结果格式
	result := make([]map[string]interface{}, 0, len(entries))
	for _, entry := range entries {
		info, err := entry.Info()
		if err != nil {
			continue
		}

		fullPath := filepath.Join(path, entry.Name())
		result = append(result, map[string]interface{}{
			"name":     entry.Name(),
			"path":     filepath.ToSlash(fullPath), // 统一使用正斜杠
			"is_dir":   entry.IsDir(),
			"size":     info.Size(),
			"mod_time": info.ModTime().Format("2006-01-02 15:04:05"),
		})
	}

	s.logAudit(AuditLogEntry{
		Timestamp:   getCurrentTimestamp(),
		Operation:   OperationList,
		Path:        path,
		IsDirectory: true,
		Success:     true,
	})

	return result, nil
}

// CreateDir 创建目录，返回创建的目录信息
func (s *FileSystemService) CreateDir(path string) (*FileOperationResult, error) {
	if err := s.validatePath(path); err != nil {
		return nil, err
	}

	if err := os.MkdirAll(path, DefaultDirPermissions); err != nil {
		return nil, fmt.Errorf("创建目录失败: %v", err)
	}

	s.logAudit(AuditLogEntry{
		Timestamp:   getCurrentTimestamp(),
		Operation:   OperationCreate,
		Path:        path,
		IsDirectory: true,
		Success:     true,
	})

	// 获取创建的目录信息
	info, err := os.Stat(path)
	if err != nil {
		// 创建成功但获取信息失败，返回基本信息
		return &FileOperationResult{
			Path:  filepath.ToSlash(path), // 统一使用正斜杠
			Name:  filepath.Base(path),
			IsDir: true,
		}, nil
	}

	return &FileOperationResult{
		Path:    filepath.ToSlash(path), // 统一使用正斜杠
		Name:    info.Name(),
		Size:    info.Size(),
		SizeStr: FormatBytes(info.Size()),
		IsDir:   true,
		ModTime: info.ModTime().Format("2006-01-02 15:04:05"),
		Mode:    info.Mode().String(),
	}, nil
}

// CreateFile 创建空文件，返回创建的文件信息
func (s *FileSystemService) CreateFile(path string) (*FileOperationResult, error) {
	if err := s.validatePath(path); err != nil {
		return nil, err
	}

	// 检查文件是否已存在
	if _, err := os.Stat(path); err == nil {
		return nil, fmt.Errorf("文件已存在")
	}

	file, err := os.Create(path)
	if err != nil {
		return nil, fmt.Errorf("创建文件失败: %v", err)
	}
	file.Close()

	s.logAudit(AuditLogEntry{
		Timestamp:   getCurrentTimestamp(),
		Operation:   OperationCreate,
		Path:        path,
		IsDirectory: false,
		Success:     true,
	})

	// 获取创建的文件信息
	info, err := os.Stat(path)
	if err != nil {
		// 创建成功但获取信息失败，返回基本信息
		return &FileOperationResult{
			Path:  filepath.ToSlash(path), // 统一使用正斜杠
			Name:  filepath.Base(path),
			IsDir: false,
			Size:  0,
		}, nil
	}

	return &FileOperationResult{
		Path:    filepath.ToSlash(path), // 统一使用正斜杠
		Name:    info.Name(),
		Size:    info.Size(),
		SizeStr: FormatBytes(info.Size()),
		IsDir:   false,
		ModTime: info.ModTime().Format("2006-01-02 15:04:05"),
		Mode:    info.Mode().String(),
	}, nil
}

// GetFileInfo 获取文件信息
func (s *FileSystemService) GetFileInfo(path string) (map[string]interface{}, error) {
	if err := s.validatePath(path); err != nil {
		return nil, err
	}

	info, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, fmt.Errorf("文件或目录不存在")
		}
		return nil, fmt.Errorf("获取文件信息失败: %v", err)
	}

	return map[string]interface{}{
		"name":     info.Name(),
		"path":     filepath.ToSlash(path), // 统一使用正斜杠
		"size":     info.Size(),
		"size_str": FormatBytes(info.Size()),
		"is_dir":   info.IsDir(),
		"mod_time": info.ModTime().Format("2006-01-02 15:04:05"),
		"mode":     info.Mode().String(),
	}, nil
}

// OpenPath 打开文件或目录（使用系统默认程序）
func (s *FileSystemService) OpenPath(path string) error {
	if err := s.validatePath(path); err != nil {
		return err
	}

	return OpenPath(path)
}

// RenamePath 重命名文件或目录，返回新文件信息
func (s *FileSystemService) RenamePath(oldPath, newPath string) (*FileOperationResult, error) {
	// 验证旧路径
	if err := s.validatePath(oldPath); err != nil {
		return nil, err
	}

	// 验证新路径
	if err := s.validatePath(newPath); err != nil {
		return nil, err
	}

	// 执行重命名
	if err := os.Rename(oldPath, newPath); err != nil {
		return nil, fmt.Errorf("重命名失败: %v", err)
	}

	s.logAudit(AuditLogEntry{
		Timestamp:   getCurrentTimestamp(),
		Operation:   OperationRename,
		Path:        newPath,
		OldPath:     oldPath,
		Success:     true,
	})

	// 获取新文件信息
	info, err := os.Stat(newPath)
	if err != nil {
		// 重命名成功但获取信息失败，返回基本信息
		return &FileOperationResult{
			Path:    filepath.ToSlash(newPath), // 统一使用正斜杠
			Name:    filepath.Base(newPath),
			OldPath: filepath.ToSlash(oldPath),
		}, nil
	}

	return &FileOperationResult{
		Path:    filepath.ToSlash(newPath), // 统一使用正斜杠
		Name:    info.Name(),
		Size:    info.Size(),
		SizeStr: FormatBytes(info.Size()),
		IsDir:   info.IsDir(),
		ModTime: info.ModTime().Format("2006-01-02 15:04:05"),
		Mode:    info.Mode().String(),
		OldPath: filepath.ToSlash(oldPath),
	}, nil
}

// ========== ZIP操作接口 ==========

// ListZipContents 列出ZIP文件内容（别名，保持向后兼容）
func (s *FileSystemService) ListZipContents(zipPath string) ([]map[string]interface{}, error) {
	return ListZipContents(zipPath)
}

// ExtractFileFromZip 从ZIP提取文件内容（别名，保持向后兼容）
func (s *FileSystemService) ExtractFileFromZip(zipPath, filePath string) (string, error) {
	return ExtractFileFromZip(zipPath, filePath)
}

// ExtractFileFromZipToTemp 从ZIP提取文件到临时目录（别名，保持向后兼容）
func (s *FileSystemService) ExtractFileFromZipToTemp(zipPath, filePath string) (string, error) {
	return ExtractFileFromZipToTemp(zipPath, filePath)
}

// GetZipFileInfo 获取ZIP文件信息
func (s *FileSystemService) GetZipFileInfo(zipPath, filePath string) (map[string]interface{}, error) {
	return GetZipFileInfo(zipPath, filePath)
}

// ========== 辅助函数 ==========

// getCurrentTimestamp 获取当前时间戳
func getCurrentTimestamp() time.Time {
	return time.Now()
}

// isInRecycleBin 检查路径是否在回收站中
func isInRecycleBin(path string) bool {
	recycleBinPath := filepath.Join(common.GetUserDataDir(), "recycle_bin")
	cleanPath := filepath.Clean(path)
	cleanBinPath := filepath.Clean(recycleBinPath)
	return len(cleanPath) >= len(cleanBinPath) && cleanPath[:len(cleanBinPath)] == cleanBinPath
}

// ========== 辅助方法 ==========

// validatePath 验证路径
func (s *FileSystemService) validatePath(path string) error {
	err := s.pathValidator.Validate(path)
	if err != nil && err.IsError {
		return err
	}
	return nil
}

// GetConfig 获取配置
func (s *FileSystemService) GetConfig() *Config {
	return s.config
}

// GetAuditLogger 获取审计日志记录器
func (s *FileSystemService) GetAuditLogger() *AuditLogger {
	return s.auditLogger
}

// GetRecycleBin 获取回收站
func (s *FileSystemService) GetRecycleBin() *RecycleBin {
	return s.recycleBin
}

// ========== 审计日志接口 ==========

// logAudit 安全记录审计日志（自动处理 nil 检查）
func (s *FileSystemService) logAudit(entry AuditLogEntry) {
	if s.auditLogger != nil {
		s.auditLogger.Log(entry)
	}
}

// logRead 记录读取操作审计日志
func (s *FileSystemService) logRead(path string, size int64, err error) {
	if s.auditLogger != nil {
		s.auditLogger.LogRead(path, size, err)
	}
}

// logWrite 记录写入操作审计日志
func (s *FileSystemService) logWrite(path string, size int64, err error) {
	if s.auditLogger != nil {
		s.auditLogger.LogWrite(path, size, err)
	}
}

// logDelete 记录删除操作审计日志
func (s *FileSystemService) logDelete(path string, isDir bool, size int64, err error) {
	if s.auditLogger != nil {
		s.auditLogger.LogDelete(path, isDir, size, err)
	}
}

// GetAuditLogs 获取审计日志
func (s *FileSystemService) GetAuditLogs(limit int) ([]map[string]interface{}, error) {
	if s.auditLogger == nil {
		return []map[string]interface{}{}, nil
	}

	logDir := filepath.Join(common.GetUserDataDir(), "logs")
	entries, err := GetRecentLogs(logDir, limit)
	if err != nil {
		return nil, err
	}

	result := make([]map[string]interface{}, len(entries))
	for i, entry := range entries {
		result[i] = map[string]interface{}{
			"timestamp":    entry.Timestamp.Format("2006-01-02 15:04:05"),
			"operation":    entry.Operation,
			"path":         entry.Path,
			"size":         entry.Size,
			"is_directory": entry.IsDirectory,
			"success":      entry.Success,
			"error":        entry.Error,
		}
	}

	return result, nil
}

// ========== 回收站接口 ==========

// GetRecycleBinEntries 获取回收站条目
func (s *FileSystemService) GetRecycleBinEntries() ([]map[string]interface{}, error) {
	if s.recycleBin == nil {
		return []map[string]interface{}{}, nil
	}

	entries := s.recycleBin.ListEntries()
	result := make([]map[string]interface{}, len(entries))

	for i, entry := range entries {
		result[i] = map[string]interface{}{
			"original_path": entry.OriginalPath,
			"deleted_path":  entry.DeletedPath,
			"deleted_time":  entry.DeletedTime.Format("2006-01-02 15:04:05"),
			"size":          entry.Size,
			"is_directory":  entry.IsDirectory,
		}
	}

	return result, nil
}

// RestoreFromRecycleBin 从回收站恢复文件
func (s *FileSystemService) RestoreFromRecycleBin(recyclePath string) error {
	if s.recycleBin == nil {
		return fmt.Errorf("回收站未初始化")
	}
	return s.recycleBin.RestoreFromRecycleBin(recyclePath)
}

// DeletePermanently 永久删除回收站中的文件
func (s *FileSystemService) DeletePermanently(recyclePath string) error {
	if s.recycleBin == nil {
		return fmt.Errorf("回收站未初始化")
	}
	return s.recycleBin.DeletePermanently(recyclePath)
}

// EmptyRecycleBin 清空回收站
func (s *FileSystemService) EmptyRecycleBin() error {
	if s.recycleBin == nil {
		return fmt.Errorf("回收站未初始化")
	}
	return s.recycleBin.Empty()
}

// ResolveShortcut 解析快捷方式（.lnk）文件，返回目标路径
func (s *FileSystemService) ResolveShortcut(lnkPath string) (targetPath string, err error) {
	// 验证路径
	if err := s.validatePath(lnkPath); err != nil {
		return "", fmt.Errorf("路径验证失败: %w", err)
	}

	// 检查文件扩展名
	if filepath.Ext(lnkPath) != ".lnk" {
		return "", fmt.Errorf("不是快捷方式文件")
	}

	// 检查文件是否存在
	if _, err := os.Stat(lnkPath); os.IsNotExist(err) {
		return "", fmt.Errorf("快捷方式文件不存在")
	}

	// 使用 Windows PowerShell 解析 lnk 文件
	// 这种方法更可靠，不需要依赖第三方库
	if runtime.GOOS == "windows" {
		// 创建 PowerShell 脚本
		psScript := fmt.Sprintf(
			"$shell = New-Object -ComObject WScript.Shell; "+
				"$shortcut = $shell.CreateShortcut('%s'); "+
				"$shortcut.TargetPath",
			lnkPath,
		)

		// 执行 PowerShell 命令
		cmd := exec.Command("powershell", "-NoProfile", "-NonInteractive", "-Command", psScript)
		output, err := cmd.Output()
		if err != nil {
			return "", fmt.Errorf("解析快捷方式失败: %w", err)
		}

		// 去除空白字符
		targetPath = string(output)
		targetPath = filepath.Clean(targetPath)

		// 如果目标路径为空，返回错误
		if targetPath == "" || targetPath == "." {
			return "", fmt.Errorf("快捷方式目标路径为空")
		}

		return targetPath, nil
	}

	// 非 Windows 系统暂不支持
	return "", fmt.Errorf("当前系统不支持快捷方式解析")
}

// Close 关闭服务，释放资源
func (s *FileSystemService) Close(ctx context.Context) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	if !s.initialized {
		return nil
	}

	// 关闭审计日志
	if s.auditLogger != nil {
		if err := s.auditLogger.Close(); err != nil {
			return fmt.Errorf("关闭审计日志失败: %w", err)
		}
	}

	s.initialized = false
	return nil
}

// ========== 全局服务实例（向后兼容）==========

var (
	globalService     *FileSystemService
	globalServiceOnce sync.Once
)

// GetGlobalService 获取全局文件系统服务实例（单例）
// 保持向后兼容，但推荐使用依赖注入
func GetGlobalService() (*FileSystemService, error) {
	var initErr error
	globalServiceOnce.Do(func() {
		globalService, initErr = NewFileSystemService(DefaultConfig())
	})
	return globalService, initErr
}

