import { loggerService } from '@logger'
import { app } from 'electron'
import fs from 'fs'
import path from 'path'

const logger = loggerService.withContext('ObsidianVaultService')
interface VaultInfo {
  path: string
  name: string
}

interface FileInfo {
  path: string
  type: 'folder' | 'markdown'
  name: string
}

class ObsidianVaultService {
  private obsidianConfigPath: string

  constructor() {
    // 根据操作系统获取Obsidian配置文件路径
    if (process.platform === 'win32') {
      this.obsidianConfigPath = path.join(app.getPath('appData'), 'obsidian', 'obsidian.json')
    } else if (process.platform === 'darwin') {
      this.obsidianConfigPath = path.join(
        app.getPath('home'),
        'Library',
        'Application Support',
        'obsidian',
        'obsidian.json'
      )
    } else {
      // Linux
      this.obsidianConfigPath = path.join(app.getPath('home'), '.config', 'obsidian', 'obsidian.json')
    }
  }

  /**
   * 获取所有的Obsidian Vault
   */
  getVaults(): VaultInfo[] {
    try {
      if (!fs.existsSync(this.obsidianConfigPath)) {
        return []
      }

      const configContent = fs.readFileSync(this.obsidianConfigPath, 'utf8')
      const config = JSON.parse(configContent)

      if (!config.vaults) {
        return []
      }

      return Object.entries(config.vaults).map(([, vault]: [string, any]) => ({
        path: vault.path,
        name: vault.name || path.basename(vault.path)
      }))
    } catch (error) {
      logger.error('Failed to get Obsidian Vault:', error)
      return []
    }
  }

  /**
   * 获取Vault中的文件夹和Markdown文件结构
   */
  getVaultStructure(vaultPath: string): FileInfo[] {
    const results: FileInfo[] = []

    try {
      // 检查vault路径是否存在
      if (!fs.existsSync(vaultPath)) {
        logger.error('Vault path does not exist:', vaultPath)
        return []
      }

      // 检查是否是目录
      const stats = fs.statSync(vaultPath)
      if (!stats.isDirectory()) {
        logger.error('Vault path is not a directory:', vaultPath)
        return []
      }

      this.traverseDirectory(vaultPath, '', results)
    } catch (error) {
      logger.error('Failed to read Vault folder structure:', error)
    }

    return results
  }

  /**
   * 递归遍历目录获取所有文件夹和Markdown文件
   */
  private traverseDirectory(dirPath: string, relativePath: string, results: FileInfo[]) {
    try {
      // 首先添加当前文件夹
      if (relativePath) {
        results.push({
          path: relativePath,
          type: 'folder',
          name: path.basename(relativePath)
        })
      }

      // 确保目录存在且可访问
      if (!fs.existsSync(dirPath)) {
        logger.error('Directory does not exist:', dirPath)
        return
      }

      let items
      try {
        items = fs.readdirSync(dirPath, { withFileTypes: true })
      } catch (err) {
        logger.error(`Failed to read directory ${dirPath}:`, err)
        return
      }

      for (const item of items) {
        // 忽略以.开头的隐藏文件夹和文件
        if (item.name.startsWith('.')) {
          continue
        }

        const newRelativePath = relativePath ? `${relativePath}/${item.name}` : item.name
        const fullPath = path.join(dirPath, item.name)

        if (item.isDirectory()) {
          this.traverseDirectory(fullPath, newRelativePath, results)
        } else if (item.isFile() && item.name.endsWith('.md')) {
          // 收集.md文件
          results.push({
            path: newRelativePath,
            type: 'markdown',
            name: item.name
          })
        }
      }
    } catch (error) {
      logger.error(`Failed to traverse directory ${dirPath}:`, error)
    }
  }

  /**
   * 获取指定Vault的文件夹和Markdown文件结构
   * @param vaultName vault名称
   */
  getFilesByVaultName(vaultName: string): FileInfo[] {
    try {
      const vaults = this.getVaults()
      const vault = vaults.find((v) => v.name === vaultName)

      if (!vault) {
        logger.error('Vault not found:', vaultName)
        return []
      }

      logger.debug('Get Vault file structure:', vault.name, vault.path)
      return this.getVaultStructure(vault.path)
    } catch (error) {
      logger.error('Failed to get Vault file structure:', error)
      return []
    }
  }
}

export default ObsidianVaultService
