/**
 * SFTP Transport — 通过 Wails IPC 调用 Go 后端 SFTP 客户端
 */

import type {
  FsTransport, FileItem, FileOperationResult, DetectTypeResult,
} from './transport'
import type { ConnectionProfile } from './connection-manager'
import {
  SftpConnect, SftpDisconnect, SftpListDir, SftpReadFile,
  SftpWriteFile, SftpGetFileInfo, SftpCreateDir, SftpCreateFile,
  SftpDeletePath, SftpRenamePath, SftpDownloadToTemp, SftpGetCommonPaths,
  SftpWriteBase64File,
} from '@bindings/u-desk/app'

function transformFile(file: any): FileItem {
  return { ...file, is_dir: file.is_dir, mod_time: file.mod_time }
}

function transformFileList(files: any[]): FileItem[] {
  return files.map(transformFile)
}

const PREVIEW_CACHE_MAX = 50

export class SftpTransport implements FsTransport {
  private profile: ConnectionProfile
  private connID: string | null = null
  private previewCache = new Map<string, string>() // remotePath -> localTempPath (LRU)
  private previewOrder: string[] = [] // LRU 排序键列表

  constructor(profile: ConnectionProfile) {
    this.profile = profile
  }

  async connect(): Promise<string> {
    const result = await SftpConnect({
      host: this.profile.host,
      port: this.profile.port || 22,
      username: this.profile.username || 'root',
      password: this.profile.password || '',
      key_path: this.profile.keyPath || '',
      key_passphrase: '',
    })
    this.connID = result
    return result
  }

  get sessionId(): string | null { return this.connID }

  async disconnect(): Promise<void> {
    if (this.connID) {
      try { await SftpDisconnect(this.connID) } catch (e) {
        console.warn('[SFTP] disconnect error:', e)
      }
      this.connID = null
    }
    this.previewCache.clear()
    this.previewOrder = []
  }

  private requireConn(): string {
    if (!this.connID) throw new Error('SFTP 未连接')
    return this.connID
  }

  // ====== 文件列表与信息 ======

  async listDir(path: string): Promise<FileItem[]> {
    return transformFileList(await SftpListDir(this.requireConn(), path))
  }

  async getFileInfo(path: string): Promise<Record<string, any>> {
    return SftpGetFileInfo(this.requireConn(), path)
  }

  // ====== 文件读写 ======

  async readFile(path: string): Promise<string> {
    return SftpReadFile(this.requireConn(), path)
  }

  async writeFile(path: string, content: string): Promise<void> {
    await SftpWriteFile({
      session_id: this.requireConn(),
      path,
      content,
    })
  }

  async saveBase64File(path: string, content: string): Promise<void> {
    if (!content) throw new Error('无效的 base64 内容')
    await SftpWriteBase64File(this.requireConn(), path, content)
  }

  // ====== 文件操作 ======

  async createFile(dirPath: string, filename: string): Promise<FileOperationResult> {
    const fullPath = dirPath.replace(/\/$/, '') + '/' + filename
    return SftpCreateFile(this.requireConn(), fullPath)
  }

  async createDir(parentPath: string, dirname: string): Promise<FileOperationResult> {
    const fullPath = parentPath.replace(/\/$/, '') + '/' + dirname
    return SftpCreateDir(this.requireConn(), fullPath)
  }

  async deletePath(path: string): Promise<FileOperationResult> {
    return SftpDeletePath(this.requireConn(), path)
  }

  async renamePath(oldPath: string, newPath: string): Promise<FileOperationResult> {
    return SftpRenamePath({
      session_id: this.requireConn(),
      old_path: oldPath,
      new_path: newPath,
    })
  }

  // ====== ZIP 操作（不支持）======

  async listZipContents(_zipPath: string): Promise<FileItem[]> {
    throw new Error('ZIP 操作在 SFTP 模式暂未实现')
  }

  async extractFileFromZip(_zipPath: string, _filePath: string): Promise<string> {
    throw new Error('ZIP 操作在 SFTP 模式暂未实现')
  }

  async extractFileFromZipToTemp(_zipPath: string, _filePath: string): Promise<string> {
    throw new Error('ZIP 操作在 SFTP 模式暂未实现')
  }

  async getZipFileInfo(_zipPath: string, _filePath: string): Promise<FileItem> {
    throw new Error('ZIP 操作在 SFTP 模式暂未实现')
  }

  // ====== 系统操作 ======

  async openPath(_path: string): Promise<void> {
    throw new Error('SFTP 模式不支持打开本地路径')
  }

  async getFileServerURL(): Promise<string> {
    const { getFileServerBaseURL } = await import('./file-server')
    return getFileServerBaseURL()
  }

  getPreviewToken(): string {
    return ''
  }

  async resolveShortcut(_lnkPath: string): Promise<any> {
    return null
  }

  async detectFileTypeByContent(_path: string): Promise<DetectTypeResult> {
    return { extension: '', category: 'unknown', mime_type: '', confidence: 0 }
  }

  async getCommonPaths(): Promise<Record<string, string>> {
    return SftpGetCommonPaths(this.requireConn())
  }

  // ====== 回收站（无）======

  async getRecycleBinEntries(): Promise<any[]> {
    return []
  }

  async restoreFromRecycleBin(_path: string): Promise<void> {}

  async deletePermanently(_path: string): Promise<void> {}

  async emptyRecycleBin(): Promise<void> {}

  // ====== 预览辅助 ======

  /** 下载远程文件到本地临时目录用于预览（带 LRU 缓存，上限 50） */
  async downloadForPreview(remotePath: string): Promise<string> {
    // 命中：移到队尾（最近使用）
    if (this.previewCache.has(remotePath)) {
      this.previewOrder = this.previewOrder.filter(p => p !== remotePath)
      this.previewOrder.push(remotePath)
      return this.previewCache.get(remotePath)!
    }
    const localPath = await SftpDownloadToTemp(this.requireConn(), remotePath)

    // 淘汰最旧条目
    if (this.previewOrder.length >= PREVIEW_CACHE_MAX) {
      const oldest = this.previewOrder.shift()!
      this.previewCache.delete(oldest)
    }

    this.previewCache.set(remotePath, localPath)
    this.previewOrder.push(remotePath)
    return localPath
  }
}
