const fs = require('fs').promises
const path = require('path')
const { defaultLogger } = require('../utils/logger');

// 创建logger实例
const logger = defaultLogger.child('WatchlistManager');

/**
 * 待看名单管理器
 * 负责管理用户的待看名单数据
 */
class WatchlistManager {
  constructor() {
    // 检测是否在pkg打包环境中运行
    const isPkg = process.pkg !== undefined;
    
    if (isPkg) {
      // 在打包环境中，使用可执行文件所在目录
      this.configDir = path.join(process.cwd(), 'data', 'watchlist.json')
    } else {
      // 在开发环境中，使用项目根目录的data文件夹
      this.configDir = path.join(__dirname, '..', '..', 'data', 'watchlist.json')
    }
    
    // 确保配置目录存在
    this.ensureConfigDir()
    
    this.defaultData = {
      items: [],
      lastUpdated: new Date().toISOString()
    }
  }

  /**
   * 确保配置目录存在
   */
  ensureConfigDir() {
    try {
      const configDirPath = path.dirname(this.configDir)
      if (!require('fs').existsSync(configDirPath)) {
        require('fs').mkdirSync(configDirPath, { recursive: true })
        logger.info('待看名单目录创建成功')
      }
    } catch (error) {
      logger.error('创建待看名单目录失败:', error)
    }
  }

  /**
   * 初始化待看名单文件
   * 如果文件不存在，则创建默认数据
   */
  async initialize() {
    try {
      // 检查文件是否存在
      await fs.access(this.configDir)
      logger.info('待看名单文件已存在')
    } catch (error) {
      // 文件不存在，创建默认文件
      logger.info('创建默认待看名单文件...')
      await this.createDefaultData()
    }
  }

  /**
   * 创建默认数据文件
   */
  async createDefaultData() {
    try {
      // 确保配置目录存在
      const configDirPath = path.dirname(this.configDir)
      await fs.mkdir(configDirPath, { recursive: true })
      
      // 检查目录是否创建成功
      try {
        await fs.access(configDirPath)
        logger.info('待看名单目录确认存在')
      } catch (accessError) {
        logger.error('待看名单目录访问失败:', accessError)
        throw new Error(`无法访问配置目录: ${configDirPath}`)
      }
      
      // 写入默认数据
      const dataContent = JSON.stringify(this.defaultData, null, 2)
      await fs.writeFile(this.configDir, dataContent, 'utf8')
      
      // 验证文件是否写入成功
      try {
        await fs.access(this.configDir)
        logger.info('默认待看名单文件创建成功')
      } catch (verifyError) {
        logger.error('待看名单文件验证失败:', verifyError)
        throw new Error('待看名单文件创建后无法访问')
      }
    } catch (error) {
      logger.error('创建默认待看名单文件失败:', error)
      throw error
    }
  }

  /**
   * 读取待看名单数据
   */
  async readData() {
    try {
      // 首先检查文件是否存在
      const exists = await this.dataExists()
      if (!exists) {
        logger.info('待看名单文件不存在，创建默认数据...')
        await this.createDefaultData()
      }
      
      const dataContent = await fs.readFile(this.configDir, 'utf8')
      const data = JSON.parse(dataContent)
      
      // 合并默认数据，确保所有必要的字段都存在
      return { ...this.defaultData, ...data }
    } catch (error) {
      logger.error('读取待看名单文件失败:', error)
      logger.info('使用默认数据...')
      // 如果读取失败，尝试创建默认数据
      try {
        await this.createDefaultData()
        return { ...this.defaultData }
      } catch (createError) {
        logger.error('创建默认数据也失败:', createError)
        // 最后返回内存中的默认数据
        return { ...this.defaultData }
      }
    }
  }

  /**
   * 保存待看名单数据
   */
  async saveData(data) {
    try {
      // 添加更新时间
      const dataToSave = {
        ...data,
        lastUpdated: new Date().toISOString()
      }
      
      await fs.writeFile(
        this.configDir,
        JSON.stringify(dataToSave, null, 2),
        'utf8'
      )
      
      logger.info('待看名单文件保存成功')
      return true
    } catch (error) {
      logger.error('保存待看名单文件失败:', error)
      throw error
    }
  }

  /**
   * 添加待看项目
   */
  async addItem(item) {
    try {
      const data = await this.readData()
      
      // 检查是否已存在相同的URL
      const existingIndex = data.items.findIndex(existingItem => existingItem.url === item.url)
      
      if (existingIndex !== -1) {
        // 如果存在，更新现有项目
        data.items[existingIndex] = {
          ...data.items[existingIndex],
          ...item,
          updatedAt: new Date().toISOString()
        }
      } else {
        // 添加新项目
        const newItem = {
          id: Date.now().toString(),
          ...item,
          createdAt: new Date().toISOString(),
          updatedAt: new Date().toISOString()
        }
        data.items.push(newItem)
      }
      
      await this.saveData(data)
      return data.items
    } catch (error) {
      logger.error('添加待看项目失败:', error)
      throw error
    }
  }

  /**
   * 删除待看项目
   */
  async removeItem(id) {
    try {
      const data = await this.readData()
      const initialLength = data.items.length
      
      data.items = data.items.filter(item => item.id !== id)
      
      if (data.items.length === initialLength) {
        throw new Error('待看项目不存在')
      }
      
      await this.saveData(data)
      return data.items
    } catch (error) {
      logger.error('删除待看项目失败:', error)
      throw error
    }
  }

  /**
   * 更新待看项目
   */
  async updateItem(id, updates) {
    try {
      const data = await this.readData()
      const itemIndex = data.items.findIndex(item => item.id === id)
      
      if (itemIndex === -1) {
        throw new Error('待看项目不存在')
      }
      
      data.items[itemIndex] = {
        ...data.items[itemIndex],
        ...updates,
        updatedAt: new Date().toISOString()
      }
      
      await this.saveData(data)
      return data.items[itemIndex]
    } catch (error) {
      logger.error('更新待看项目失败:', error)
      throw error
    }
  }

  /**
   * 获取所有待看项目
   */
  async getAllItems() {
    try {
      const data = await this.readData()
      return data.items
    } catch (error) {
      logger.error('获取待看项目失败:', error)
      throw error
    }
  }

  /**
   * 获取配置文件路径
   */
  getConfigPath() {
    return this.configDir
  }

  /**
   * 检查配置文件是否存在
   */
  async dataExists() {
    try {
      await fs.access(this.configDir)
      return true
    } catch (error) {
      return false
    }
  }
}

module.exports = WatchlistManager 