// [fs-only] 数据库客户端模块已移除（feature/fs-only 分支）
// 保留模块：文件系统 | Markdown编辑器 | 版本历史(抽屉) | 系统信息 | 更新检查 | PDF导出
// 顶部Tab仅：file-system（数据库 db-cli 已删除）
package main

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	stdruntime "runtime"
	"strings"
	"sync"
	"time"

	"golang.org/x/sys/windows/registry"
	"u-desk/internal/api"
	"u-desk/internal/common"
	"u-desk/internal/filesystem"
	"u-desk/internal/service"
	"u-desk/internal/sftp"
	"u-desk/internal/storage"
	"u-desk/internal/storage/models"
	"u-desk/internal/system"

	"github.com/wailsapp/wails/v3/pkg/application"
	"github.com/wailsapp/wails/v3/pkg/w32"
)

// App 应用结构体
type App struct {
	ctx           context.Context
	mainWindow    *application.WebviewWindow
	updateAPI     *api.UpdateAPI
	updateTicker  *time.Ticker
	configAPI     *api.ConfigAPI
	pdfAPI        *api.PdfAPI
	filesystem    *filesystem.FileSystemService
	sftpService   *sftp.Service
	isAlwaysOnTop bool
	mu            sync.Mutex
}

// App 方法命名约定：
// - 多参数操作 → XxxRequest 结构体（Wails 自动生成 TS 类型）
// - 单参数查询/简单操作 → 直接参数

// NewApp 创建新的应用实例
func NewApp() *App {
	return &App{}
}

// SetMainWindow 设置主窗口引用（由 main.go 在创建窗口后调用）
func (a *App) SetMainWindow(w *application.WebviewWindow) {
	a.mainWindow = w
}

// ServiceStartup Wails v3 服务启动生命周期（替代 v2 的 Startup）
func (a *App) ServiceStartup(ctx context.Context, _ application.ServiceOptions) error {
	a.ctx = ctx

	// 1. 核心初始化：SQLite（必须同步，很快）
	if _, err := storage.InitFast(); err != nil {
		return fmt.Errorf("SQLite 初始化失败，应用无法启动: %w", err)
	}

	// 2. 初始化配置服务
	configService, err := api.NewConfigAPI()
	if err != nil {
		return fmt.Errorf("配置服务初始化失败: %w", err)
	}
	a.configAPI = configService

	// 2.5. 迁移旧配置
	_ = a.configAPI.MigrateTabConfig()

	// 2.6. 初始化PDF导出API
	fmt.Println("[启动] 初始化PDF导出模块...")
	pdfAPI, err := api.NewPdfAPI()
	if err != nil {
		fmt.Printf("[启动] PDF导出API初始化失败: %v\n", err)
	} else {
		a.pdfAPI = pdfAPI
		fmt.Println("[启动] PDF导出模块初始化完成")
	}

	// 3. 初始化版本号（提前触发缓存，避免后续重复计算）
	version := service.GetCurrentVersion()
	fmt.Printf("[启动] 当前版本: %s\n", version)

	// 4. 读取配置，获取可见的 Tabs
	visibleTabs := a.getVisibleTabs()
	fmt.Printf("[启动] 可用的模块: %v\n", visibleTabs)

	// 4. 根据配置初始化模块（条件初始化）
	if err := a.initModulesByConfig(visibleTabs); err != nil {
		return fmt.Errorf("模块初始化失败: %w", err)
	}

	// 5. 清理遗留的 SFTP 临时预览文件
	sftp.CleanupTempFiles()

	// 6. 异步初始化：UpdateAPI（涉及网络请求，完全异步）
	go func() {
		if updateAPI, err := api.NewUpdateAPI("https://c.1216.top/last-version.json"); err == nil {
			a.mu.Lock()
			a.updateAPI = updateAPI
			a.mu.Unlock()

			a.updateAPI.SetContext(ctx)
			a.updateAPI.SetEventEmitter(func(name string, data ...any) {
				if a.mainWindow != nil {
					a.mainWindow.EmitEvent(name, data...)
				}
			})
			a.startAutoUpdateCheck()
		}
	}()

	return nil
}

// getVisibleTabs 获取配置中的可见 Tabs
func (a *App) getVisibleTabs() []string {
	config, err := a.configAPI.GetAppConfig()
	if err != nil {
		fmt.Printf("[启动] 读取配置失败，使用默认配置: %v\n", err)
		return common.DefaultVisibleTabs
	}

	success, ok := config["success"].(bool)
	if !ok || !success {
		fmt.Printf("[启动] 配置读取失败，使用默认配置\n")
		return common.DefaultVisibleTabs
	}

	data, ok := config["data"].(map[string]interface{})
	if !ok {
		return common.DefaultVisibleTabs
	}

	visibleTabsInterface, ok := data["visibleTabs"].([]interface{})
	if !ok {
		return common.DefaultVisibleTabs
	}

	visibleTabs := common.InterfaceSliceToStringSlice(visibleTabsInterface)

	if len(visibleTabs) == 0 {
		return common.DefaultVisibleTabs
	}

	return visibleTabs
}

// initModulesByConfig 根据配置初始化模块
func (a *App) initModulesByConfig(visibleTabs []string) error {
	if common.Contains(visibleTabs, common.TabFileSystem) {
		fmt.Println("[启动] 初始化文件系统模块...")

		fsConfig := filesystem.DefaultConfig()
		var err error
		a.filesystem, err = filesystem.NewFileSystemService(fsConfig)
		if err != nil {
			return fmt.Errorf("文件系统服务初始化失败: %w", err)
		}

		go a.startFileServer()

		fmt.Println("[启动] 文件系统模块初始化完成")
	} else {
		fmt.Println("[启动] 跳过文件系统模块（未启用）")
	}

	return nil
}

// startFileServer 启动文件服务器
func (a *App) startFileServer() {
	if _, err := filesystem.StartLocalFileServer(); err != nil {
		fmt.Printf("[文件服务器] 启动失败: %v\n", err)
		return
	}
	fmt.Printf("[文件服务器] 启动在 http://%s\n", filesystem.GetLocalFileServerAddr())
}

// ServiceShutdown Wails v3 服务关闭生命周期（替代 v2 的 Shutdown）
func (a *App) ServiceShutdown() error {
	if a.updateTicker != nil {
		a.updateTicker.Stop()
	}

	shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if a.filesystem != nil {
		fmt.Println("[文件系统服务] 正在关闭...")
		if err := a.filesystem.Close(shutdownCtx); err != nil {
			fmt.Printf("[文件系统服务] 关闭失败: %v\n", err)
		} else {
			fmt.Println("[文件系统服务] 已关闭")
		}
	}

	fmt.Println("[文件服务器] 正在关闭...")
	if err := filesystem.ShutdownLocalFileServer(); err != nil {
		fmt.Printf("[文件服务器] 关闭失败: %v\n", err)
	} else {
		fmt.Println("[文件服务器] 已关闭")
	}

	// 关闭所有 SFTP 连接 + 清理临时文件
	if a.sftpService != nil {
		sftp.GetManager().Shutdown()
	}
	sftp.CleanupTempFiles()

	return nil
}

// GetSystemInfo 获取系统信息
func (a *App) GetSystemInfo() (map[string]interface{}, error) {
	return system.GetSystemInfo()
}

// GetCPUInfo 获取 CPU 信息
func (a *App) GetCPUInfo() (map[string]interface{}, error) {
	return system.GetCPUInfo()
}

// GetMemoryInfo 获取内存信息
func (a *App) GetMemoryInfo() (map[string]interface{}, error) {
	return system.GetMemoryInfo()
}

// GetDiskInfo 获取磁盘信息
func (a *App) GetDiskInfo() ([]map[string]interface{}, error) {
	return system.GetDiskInfo()
}

// ReadFile 读取文件
func (a *App) ReadFile(path string) (string, error) {
	return a.filesystem.ReadFile(path)
}

// WriteFileRequest 写入文件请求结构体
type WriteFileRequest struct {
	Path    string `json:"path"`
	Content string `json:"content"`
}

// WriteFile 写入文件
func (a *App) WriteFile(req WriteFileRequest) error {
	return a.filesystem.WriteFile(req.Path, req.Content)
}

// SaveBase64FileRequest 保存 Base64 编码的二进制文件
type SaveBase64FileRequest struct {
	Path    string `json:"path"`
	Content string `json:"content"` // base64 编码的文件内容
}

// SaveBase64File 将 base64 内容解码后写入文件（用于图片等二进制数据）
func (a *App) SaveBase64File(req SaveBase64FileRequest) error {
	return a.filesystem.SaveBase64File(req.Path, req.Content)
}

// ListDir 列出目录
func (a *App) ListDir(path string) ([]map[string]interface{}, error) {
	return a.filesystem.ListDir(path)
}

// CreateDir 创建目录
func (a *App) CreateDir(path string) (*filesystem.FileOperationResult, error) {
	return a.filesystem.CreateDir(path)
}

// CreateFile 创建文件
func (a *App) CreateFile(path string) (*filesystem.FileOperationResult, error) {
	return a.filesystem.CreateFile(path)
}

// DeletePath 删除文件或目录
func (a *App) DeletePath(path string) (*filesystem.FileOperationResult, error) {
	return a.filesystem.DeletePath(path)
}

// RenamePathRequest 重命名文件或目录请求结构体
type RenamePathRequest struct {
	OldPath string `json:"oldPath"`
	NewPath string `json:"newPath"`
}

// RenamePath 重命名文件或目录
func (a *App) RenamePath(req RenamePathRequest) (*filesystem.FileOperationResult, error) {
	return a.filesystem.RenamePath(req.OldPath, req.NewPath)
}

// GetFileInfo 获取文件信息
func (a *App) GetFileInfo(path string) (map[string]interface{}, error) {
	return a.filesystem.GetFileInfo(path)
}

// GetEnvVars 获取环境变量
func (a *App) GetEnvVars() (map[string]string, error) {
	envVars := make(map[string]string)
	for _, env := range os.Environ() {
		if key, value, found := strings.Cut(env, "="); found {
			envVars[key] = value
		}
	}
	return envVars, nil
}

// OpenPath 使用系统默认程序打开文件或目录
func (a *App) OpenPath(path string) error {
	return a.filesystem.OpenPath(path)
}

// ========== Zip 文件操作接口 ==========

// ListZipContents 列出 zip 文件内容
func (a *App) ListZipContents(zipPath string) ([]map[string]interface{}, error) {
	return a.filesystem.ListZipContents(zipPath)
}

// ExtractFileFromZip 从 zip 文件中提取单个文件内容
func (a *App) ExtractFileFromZip(zipPath, filePath string) (string, error) {
	return a.filesystem.ExtractFileFromZip(zipPath, filePath)
}

// ExtractFileFromZipToTemp 从 zip 文件中提取单个文件到临时目录
func (a *App) ExtractFileFromZipToTemp(zipPath, filePath string) (string, error) {
	return a.filesystem.ExtractFileFromZipToTemp(zipPath, filePath)
}

// GetZipFileInfo 获取 zip 文件中特定文件的信息
func (a *App) GetZipFileInfo(zipPath, filePath string) (map[string]interface{}, error) {
	return a.filesystem.GetZipFileInfo(zipPath, filePath)
}

// ResolveShortcut 解析快捷方式文件，返回目标路径信息
func (a *App) ResolveShortcut(lnkPath string) (map[string]interface{}, error) {
	targetPath, err := a.filesystem.ResolveShortcut(lnkPath)
	if err != nil {
		return map[string]interface{}{
			"success": false,
			"message": err.Error(),
		}, err
	}

	fileInfo, err := a.filesystem.GetFileInfo(targetPath)
	if err != nil {
		return map[string]interface{}{
			"success":          true,
			"targetPath":       targetPath,
			"targetExists":     false,
			"targetAccessible": false,
		}, nil
	}

	return map[string]interface{}{
		"success":          true,
		"targetPath":       targetPath,
		"targetExists":     true,
		"targetAccessible": true,
		"targetInfo":       fileInfo,
	}, nil
}

// getWindowsSpecialFolder 从注册表读取 Windows 特殊文件夹的真实路径
func getWindowsSpecialFolder(guid string, fallbackName string) string {
	key, err := registry.OpenKey(registry.CURRENT_USER,
		`Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders`,
		registry.READ)
	if err != nil {
		return ""
	}
	defer key.Close()

	val, _, err := key.GetStringValue(guid)
	if err != nil || val == "" {
		return ""
	}

	path := os.ExpandEnv(val)
	if _, err := os.Stat(path); err != nil {
		return ""
	}
	return path
}

// GetCommonPaths 获取常用系统路径
func (a *App) GetCommonPaths() (map[string]string, error) {
	homeDir, err := os.UserHomeDir()
	if err != nil {
		return nil, err
	}

	paths := map[string]string{
		"home": homeDir,
	}

	folderGUIDs := map[string]string{
		"desktop":   "{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}",
		"documents": "{D20B4C7F-5EA7-424C-B25E-039F6F1FCC8A}",
		"downloads": "{374DE290-123F-4565-9164-39C4925E467B}",
	}
	for name, guid := range folderGUIDs {
		if p := getWindowsSpecialFolder(guid, name); p != "" {
			paths[name] = p
		} else {
			paths[name] = filepath.Join(homeDir, strings.ToUpper(name[:1])+name[1:])
		}
	}

	if stdruntime.GOOS == "windows" {
		for _, drive := range "ABCDEFGHIJKLMNOPQRSTUVWXYZ" {
			path := string(drive) + ":\\"
			if _, err := os.Stat(path); err == nil {
				key := fmt.Sprintf("root_%c", drive)
				paths[key] = path
			}
		}
	}

	return paths, nil
}

// Reload 重新加载窗口（用于菜单项）
func (a *App) Reload() {
	if a.mainWindow != nil {
		a.mainWindow.Reload()
	}
}

// ClearCache 清理本地缓存（用于菜单项）
func (a *App) ClearCache() {
	if a.mainWindow != nil {
		a.mainWindow.EmitEvent("clear-cache")
	}
}

// ========== 窗口控制方法 ==========

// WindowMinimize 最小化窗口
func (a *App) WindowMinimize() {
	if a.mainWindow != nil {
		a.mainWindow.Minimise()
	}
}

// WindowMaximize 最大化/还原窗口
func (a *App) WindowMaximize() {
	if a.mainWindow == nil {
		return
	}
	if a.mainWindow.IsMaximised() {
		a.mainWindow.UnMaximise()
	} else {
		a.mainWindow.Maximise()
	}
}

// WindowClose 关闭窗口
func (a *App) WindowClose() {
	application.Get().Quit()
}

// WindowIsMaximized 检查窗口是否最大化
func (a *App) WindowIsMaximized() bool {
	if a.mainWindow != nil {
		return a.mainWindow.IsMaximised()
	}
	return false
}

// WindowToggleAlwaysOnTop 切换窗口置顶
func (a *App) WindowToggleAlwaysOnTop() bool {
	if a.mainWindow == nil {
		return false
	}
	a.isAlwaysOnTop = !a.isAlwaysOnTop
	a.mainWindow.SetAlwaysOnTop(a.isAlwaysOnTop)
	return a.isAlwaysOnTop
}

// SetWindowTitleBarColor 设置原生标题栏颜色 + 主题模式（0x00BBGGRR 格式）
func (a *App) SetWindowTitleBarColor(color uint32, isDark bool) {
	if a.mainWindow == nil || stdruntime.GOOS != "windows" {
		return
	}
	hwnd := uintptr(a.mainWindow.NativeWindow())
	if hwnd == 0 {
		return
	}
	w32.SetTheme(hwnd, isDark)
	w32.SetTitleBarColour(hwnd, color)
}

// ========== 版本更新管理接口 ==========

// requireUpdateAPI 检查 updateAPI 是否已初始化
func (a *App) requireUpdateAPI() (*api.UpdateAPI, error) {
	a.mu.Lock()
	defer a.mu.Unlock()
	if a.updateAPI == nil {
		return nil, fmt.Errorf("更新功能正在初始化中")
	}
	return a.updateAPI, nil
}

// CheckUpdate 检查更新
func (a *App) CheckUpdate() (map[string]interface{}, error) {
	api, err := a.requireUpdateAPI()
	if err != nil {
		return nil, err
	}
	return api.CheckUpdate()
}

// GetCurrentVersion 获取当前版本号
func (a *App) GetCurrentVersion() (map[string]interface{}, error) {
	api, err := a.requireUpdateAPI()
	if err != nil {
		return nil, err
	}
	return api.GetCurrentVersion()
}

// GetUpdateConfig 获取更新配置
func (a *App) GetUpdateConfig() (map[string]interface{}, error) {
	api, err := a.requireUpdateAPI()
	if err != nil {
		return nil, err
	}
	return api.GetUpdateConfig()
}

// SetUpdateConfig 设置更新配置
func (a *App) SetUpdateConfig(autoCheckEnabled bool, checkIntervalMinutes int, checkURL string) (map[string]interface{}, error) {
	api, err := a.requireUpdateAPI()
	if err != nil {
		return nil, err
	}
	return api.SetUpdateConfig(autoCheckEnabled, checkIntervalMinutes, checkURL)
}

// DownloadUpdate 下载更新包
func (a *App) DownloadUpdate(downloadURL string) (map[string]interface{}, error) {
	api, err := a.requireUpdateAPI()
	if err != nil {
		return nil, err
	}
	return api.DownloadUpdate(downloadURL)
}

// InstallUpdate 安装更新包
func (a *App) InstallUpdate(installerPath string, autoRestart bool) (map[string]interface{}, error) {
	api, err := a.requireUpdateAPI()
	if err != nil {
		return nil, err
	}
	return api.InstallUpdate(installerPath, autoRestart)
}

// InstallUpdateWithHash 安装更新包（带哈希验证）
func (a *App) InstallUpdateWithHash(installerPath string, autoRestart bool, expectedHash string, hashType string) (map[string]interface{}, error) {
	api, err := a.requireUpdateAPI()
	if err != nil {
		return nil, err
	}
	return api.InstallUpdateWithHash(installerPath, autoRestart, expectedHash, hashType)
}

// VerifyUpdateFile 验证更新文件哈希值
func (a *App) VerifyUpdateFile(filePath string, expectedHash string, hashType string) (map[string]interface{}, error) {
	api, err := a.requireUpdateAPI()
	if err != nil {
		return nil, err
	}
	return api.VerifyUpdateFile(filePath, expectedHash, hashType)
}

// startAutoUpdateCheck 启动自动更新检查
func (a *App) startAutoUpdateCheck() {
	if a.updateAPI == nil {
		return
	}

	config, err := a.updateAPI.GetUpdateConfig()
	if err != nil {
		return
	}
	success, ok := config["success"].(bool)
	if !ok || !success {
		return
	}

	configData, ok := config["data"].(map[string]interface{})
	if !ok {
		return
	}

	autoCheckEnabled, ok := configData["auto_check_enabled"].(bool)
	if !ok || !autoCheckEnabled {
		return
	}

	interval, ok := configData["check_interval_minutes"].(int)
	if !ok || interval <= 0 {
		interval = 5
	}

	go a.checkUpdate()

	a.updateTicker = time.NewTicker(time.Duration(interval) * time.Minute)
	go func() {
		for range a.updateTicker.C {
			a.checkUpdate()
		}
	}()
}

// checkUpdate 执行更新检查
func (a *App) checkUpdate() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("[自动检查更新] 发生错误: %v\n", r)
		}
	}()

	a.mu.Lock()
	api := a.updateAPI
	a.mu.Unlock()

	if api == nil {
		return
	}

	result, err := api.CheckUpdate()
	if err != nil {
		return
	}

	success, ok := result["success"].(bool)
	if !ok || !success {
		return
	}

	data, ok := result["data"].(map[string]interface{})
	if !ok {
		return
	}

	hasUpdate, ok := data["has_update"].(bool)
	if ok && hasUpdate && a.mainWindow != nil {
		a.mainWindow.EmitEvent("update-available", data)
	}
}

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

// GetAuditLogs 获取审计日志
func (a *App) GetAuditLogs(limit int) ([]map[string]interface{}, error) {
	return a.filesystem.GetAuditLogs(limit)
}

// ========== 文件服务器接口 ==========

// GetFileServerURL 获取本地文件服务器的URL
func (a *App) GetFileServerURL() string {
	return fmt.Sprintf("http://%s", filesystem.GetLocalFileServerAddr())
}

// DetectFileTypeByContent 通过文件内容检测文件类型
func (a *App) DetectFileTypeByContent(path string) (map[string]interface{}, error) {
	return filesystem.DetectFileTypeByContentSimple(path)
}

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

// GetRecycleBinEntries 获取回收站条目
func (a *App) GetRecycleBinEntries() ([]map[string]interface{}, error) {
	return a.filesystem.GetRecycleBinEntries()
}

// RestoreFromRecycleBin 从回收站恢复文件
func (a *App) RestoreFromRecycleBin(recyclePath string) error {
	return a.filesystem.RestoreFromRecycleBin(recyclePath)
}

// DeletePermanently 永久删除回收站中的文件
func (a *App) DeletePermanently(recyclePath string) error {
	return a.filesystem.DeletePermanently(recyclePath)
}

// EmptyRecycleBin 清空回收站
func (a *App) EmptyRecycleBin() error {
	return a.filesystem.EmptyRecycleBin()
}

// ========== 应用配置接口 ==========

// GetAppConfig 获取应用配置
func (a *App) GetAppConfig() (map[string]interface{}, error) {
	if a.configAPI == nil {
		return nil, fmt.Errorf("配置服务正在初始化中")
	}
	return a.configAPI.GetAppConfig()
}

// SaveAppConfigRequest 保存应用配置请求
type SaveAppConfigRequest struct {
	Tabs        []api.AppTabDefinition `json:"tabs"`
	VisibleTabs []string               `json:"visibleTabs"`
	DefaultTab  string                 `json:"defaultTab"`
}

// SaveAppConfig 保存应用配置
func (a *App) SaveAppConfig(req SaveAppConfigRequest) (map[string]interface{}, error) {
	if a.configAPI == nil {
		return nil, fmt.Errorf("配置服务正在初始化中")
	}

	oldConfig, _ := a.configAPI.GetAppConfig()
	var oldVisibleTabs []string
	if success, ok := oldConfig["success"].(bool); ok && success {
		if data, ok := oldConfig["data"].(map[string]interface{}); ok {
			if vtInterface, ok := data["visibleTabs"].([]interface{}); ok {
				oldVisibleTabs = common.InterfaceSliceToStringSlice(vtInterface)
			}
		}
	}

	apiReq := api.SaveAppConfigRequest{
		Tabs:        req.Tabs,
		VisibleTabs: req.VisibleTabs,
		DefaultTab:  req.DefaultTab,
	}

	result, err := a.configAPI.SaveAppConfig(apiReq)
	if err != nil {
		return result, err
	}

	if success, ok := result["success"].(bool); ok && success {
		a.handleNewlyEnabledModules(oldVisibleTabs, req.VisibleTabs)
	}

	return result, nil
}

// handleNewlyEnabledModules 处理新启用的模块
func (a *App) handleNewlyEnabledModules(oldTabs, newTabs []string) {
	newlyEnabled := common.Difference(newTabs, oldTabs)

	if len(newlyEnabled) == 0 {
		return
	}

	fmt.Printf("[模块] 检测到新启用的模块: %v\n", newlyEnabled)

	for _, tab := range newlyEnabled {
		switch tab {
		case common.TabFileSystem:
			a.initFilesystemModule()
		case common.TabDevice:
			fmt.Println("[模块] 设备测试模块已启用")
		}
	}
}

// initFilesystemModule 延迟初始化文件系统模块
func (a *App) initFilesystemModule() {
	if a.filesystem != nil {
		fmt.Println("[模块] 文件系统模块已初始化，跳过")
		return
	}

	fmt.Println("[模块] 延迟初始化文件系统模块...")
	fsConfig := filesystem.DefaultConfig()

	var err error
	a.filesystem, err = filesystem.NewFileSystemService(fsConfig)
	if err != nil {
		fmt.Printf("[模块] 文件系统模块初始化失败: %v\n", err)
		return
	}

	go a.startFileServer()

	fmt.Println("[模块] 文件系统模块初始化完成")
}

// ExportPDF 导出PDF文件
func (a *App) ExportPDF(content string, title string, fileName string, fontSize int, pageWidth int, pageHeight int) (map[string]interface{}, error) {
	if a.pdfAPI == nil {
		return map[string]interface{}{
			"success": false,
			"message": "PDF导出功能未初始化",
		}, fmt.Errorf("PDF导出功能未初始化")
	}

	req := api.PdfExportRequest{
		Content:    content,
		Title:      title,
		FileName:   fileName,
		FontSize:   fontSize,
		PageWidth:  pageWidth,
		PageHeight: pageHeight,
	}

	result, err := a.pdfAPI.ExportMarkdownToPDF(req)
	if err != nil {
		return map[string]interface{}{
			"success": false,
			"message": err.Error(),
		}, err
	}

	return map[string]interface{}{
		"success": result.Success,
		"message": result.Message,
		"path":    result.Path,
		"size":    result.Size,
	}, nil
}

// SelectPDFSaveDirectory 选择PDF保存目录
func (a *App) SelectPDFSaveDirectory() (string, error) {
	if a.pdfAPI == nil {
		return "", fmt.Errorf("PDF导出功能未初始化")
	}

	return a.pdfAPI.SelectDirectory()
}

// ========== SFTP 接口 ==========

func (a *App) ensureSftpService() *sftp.Service {
	a.mu.Lock()
	defer a.mu.Unlock()
	if a.sftpService == nil {
		a.sftpService = sftp.NewService()
	}
	return a.sftpService
}

// SftpConnectRequest SFTP 连接请求
type SftpConnectRequest struct {
	Host         string `json:"host"`
	Port         int    `json:"port"`
	Username     string `json:"username"`
	Password     string `json:"password"`
	KeyPath      string `json:"key_path"`
	KeyPassphrase string `json:"key_passphrase"`
}

// SftpConnect 建立 SFTP 连接，返回连接标识符 connID
func (a *App) SftpConnect(req SftpConnectRequest) (string, error) {
	config := &sftp.Config{
		Host:          req.Host,
		Port:          req.Port,
		Username:      req.Username,
		Password:      req.Password,
		KeyPath:       req.KeyPath,
		KeyPassphrase: req.KeyPassphrase,
	}
	if config.Port == 0 { config.Port = 22 }
	if config.Timeout == 0 { config.Timeout = 15 * time.Second }

	svc := a.ensureSftpService()
	_, err := svc.GetManager().Connect(config)
	if err != nil {
		return "", sftp.ToUserMessage(err)
	}

	connID := sftp.ConnID(config.Host, config.Port)
	return connID, nil
}

// SftpDisconnect 断开 SFTP 连接
func (a *App) SftpDisconnect(connID string) error {
	parts := strings.SplitN(connID, ":", 2)
	if len(parts) < 2 {
		return fmt.Errorf("无效的连接标识符")
	}
	host := parts[0]
	port, err := strconv.Atoi(parts[1])
	if err != nil {
		return fmt.Errorf("无效的端口号")
	}

	sftp.GetManager().Disconnect(host, port)
	return nil
}

// SftpListDir SFTP 列出目录
func (a *App) SftpListDir(connID string, dirPath string) ([]map[string]interface{}, error) {
	return a.ensureSftpService().ListDir(connID, dirPath)
}

// SftpReadFile SFTP 读取文件内容
func (a *App) SftpReadFile(connID string, filePath string) (string, error) {
	return a.ensureSftpService().ReadFile(connID, filePath)
}

// SftpWriteFileRequest SFTP 写入请求
type SftpWriteFileRequest struct {
	SessionID string `json:"session_id"`
	Path      string `json:"path"`
	Content   string `json:"content"`
}

// SftpWriteFile SFTP 写入文件
func (a *App) SftpWriteFile(req SftpWriteFileRequest) error {
	return a.ensureSftpService().WriteFile(req.SessionID, req.Path, req.Content)
}

// SftpWriteBase64File SFTP 写入 base64 编码的二进制文件（粘贴图片等）
func (a *App) SftpWriteBase64File(sessionID, filePath, base64Content string) error {
	return a.ensureSftpService().WriteBase64File(sessionID, filePath, base64Content)
}

// SftpGetFileInfo SFTP 获取文件信息
func (a *App) SftpGetFileInfo(connID string, filePath string) (map[string]interface{}, error) {
	return a.ensureSftpService().GetFileInfo(connID, filePath)
}

// SftpCreateDir SFTP 创建目录
func (a *App) SftpCreateDir(connID string, dirPath string) (*filesystem.FileOperationResult, error) {
	return a.ensureSftpService().CreateDir(connID, dirPath)
}

// SftpCreateFile SFTP 创建文件
func (a *App) SftpCreateFile(connID string, filePath string) (*filesystem.FileOperationResult, error) {
	return a.ensureSftpService().CreateFile(connID, filePath)
}

// SftpDeletePath SFTP 删除文件或目录
func (a *App) SftpDeletePath(connID string, filePath string) (*filesystem.FileOperationResult, error) {
	return a.ensureSftpService().DeletePath(connID, filePath)
}

// SftpRenamePathRequest SFTP 重命名请求
type SftpRenamePathRequest struct {
	SessionID string `json:"session_id"`
	OldPath   string `json:"old_path"`
	NewPath   string `json:"new_path"`
}

// SftpRenamePath SFTP 重命名文件或目录
func (a *App) SftpRenamePath(req SftpRenamePathRequest) (*filesystem.FileOperationResult, error) {
	return a.ensureSftpService().RenamePath(req.SessionID, req.OldPath, req.NewPath)
}

// SftpDownloadToTemp 下载远程文件到本地临时目录（用于预览）
func (a *App) SftpDownloadToTemp(connID string, remotePath string) (string, error) {
	return a.ensureSftpService().DownloadToTemp(connID, remotePath)
}

// SftpGetCommonPaths 获取 SFTP 远程主机常用路径
func (a *App) SftpGetCommonPaths(connID string) (map[string]string, error) {
	return a.ensureSftpService().GetCommonPaths(connID)
}

// SftpGetSystemInfo 获取 SFTP 远程主机系统信息（CPU/内存/磁盘）
func (a *App) SftpGetSystemInfo(connID string) (map[string]interface{}, error) {
	return a.ensureSftpService().GetSystemInfo(connID)
}

// --- 连接配置 CRUD (SQLite 持久化) ---

type SaveProfileRequest struct {
	ID            *uint      `json:"id"`
	Name          string     `json:"name"`
	Host          string     `json:"host"`
	Port          int        `json:"port"`
	Username      string     `json:"username"`
	Password      string     `json:"password"`
	KeyPath       string     `json:"key_path"`
	Type          string     `json:"type"`
	Token         string     `json:"token"`
	LastConnected *int64     `json:"last_connected"`
}

var profileSvc *service.ProfileService

func (a *App) ensureProfileSvc() *service.ProfileService {
	if profileSvc == nil {
		profileSvc = service.NewProfileService()
	}
	return profileSvc
}

func (a *App) LoadConnectionProfiles() ([]map[string]interface{}, error) {
	list, err := a.ensureProfileSvc().ListProfiles()
	if err != nil { return nil, err }
	result := make([]map[string]interface{}, len(list))
	for i, p := range list {
		result[i] = map[string]interface{}{
			"id":             float64(p.ID),
			"name":           p.Name,
			"host":           p.Host,
			"port":           p.Port,
			"username":       p.Username,
			"password":       p.Password,
			"keyPath":        p.KeyPath,
			"type":           p.Type,
			"token":          p.Token,
			"lastConnected":  p.LastConnected,
			"sortOrder":      float64(p.SortOrder),
		}
	}
	return result, nil
}

func (a *App) SaveConnectionProfile(req SaveProfileRequest) (map[string]interface{}, error) {
	p := &models.ConnectionProfile{
		Name: req.Name, Host: req.Host, Port: req.Port,
		Username: req.Username, Password: req.Password,
		KeyPath: req.KeyPath, Type: req.Type, Token: req.Token,
	}
	if req.LastConnected != nil {
		t := time.Unix(*req.LastConnected, 0)
		p.LastConnected = &t
	}
	if req.ID != nil {
		p.ID = *req.ID
	}
	if err := a.ensureProfileSvc().SaveProfile(p); err != nil {
		return nil, err
	}
	return map[string]interface{}{"id": float64(p.ID), "success": true}, nil
}

func (a *App) DeleteConnectionProfile(id uint) error {
	return a.ensureProfileSvc().DeleteProfile(id)
}

func (a *App) GetLocalSystemInfo() (map[string]interface{}, error) {
	info := make(map[string]interface{})

	cpuInfo, err := system.GetCPUInfo()
	if err == nil && cpuInfo != nil {
		if v, ok := cpuInfo["usage"].(string); ok { info["cpu_usage"] = v }
	}

	memInfo, err := system.GetMemoryInfo()
	if err == nil && memInfo != nil {
		if v, ok := memInfo["usage"].(string); ok { info["mem_usage"] = v }
	}

	diskInfos, err := system.GetDiskInfo()
	if err == nil && len(diskInfos) > 0 {
		if v, ok := diskInfos[0]["usage"].(string); ok { info["disk_usage"] = v }
	}

	return info, nil
}
