import { app, shell, BrowserWindow, protocol, nativeTheme } from 'electron'
import { join } from 'path'
import { optimizer, is, platform } from '@electron-toolkit/utils'
import { checkUpdate } from './update'
import mainIpcMain, { cleanup } from './ipcMain'
import { initAnalytics, trackDailyActive } from './analytics'
import { initProxy } from './network/proxy'
import { needsLegacyMigration, migrateFromLegacyDir, ensureAppDirs } from './paths'
import { migrateAllDatabases, checkMigrationNeeded } from './database/core'

class MainProcess {
  mainWindow: BrowserWindow | null
  constructor() {
    // 主窗口
    this.mainWindow = null

    // 设置应用程序名称
    if (process.platform === 'win32') app.setAppUserModelId(app.getName())
    // 初始化
    this.checkApp().then(async (lockObtained) => {
      if (lockObtained) {
        await this.init()
      }
    })
  }

  // 单例锁
  async checkApp() {
    if (!app.requestSingleInstanceLock()) {
      app.quit()
      // 未获得锁
      return false
    }
    // 聚焦到当前程序
    else {
      app.on('second-instance', () => {
        if (this.mainWindow) {
          this.mainWindow.show()
          if (this.mainWindow.isMinimized()) this.mainWindow.restore()
          this.mainWindow.focus()
        }
      })
      // 获得锁
      return true
    }
  }

  // 初始化程序
  async init() {
    initAnalytics()

    // 执行数据目录迁移（从 Documents/ChatLab 迁移到 userData）
    this.migrateDataIfNeeded()

    // 确保应用目录存在
    ensureAppDirs()

    // 执行数据库 schema 迁移（确保所有数据库在 Worker 查询前已是最新 schema）
    this.migrateDatabasesIfNeeded()

    initProxy() // 初始化代理配置

    // 暂不注册自定义协议，避免触发系统 URL 协议关联提示

    // 应用程序准备好之前注册
    protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }])

    // 主应用程序事件
    this.mainAppEvents()
  }

  // 从旧目录迁移数据（静默迁移）
  migrateDataIfNeeded() {
    if (needsLegacyMigration()) {
      console.log('[Main] Legacy data migration needed, starting migration...')
      const result = migrateFromLegacyDir()
      if (result.success) {
        console.log(`[Main] Migration completed. Migrated: ${result.migratedDirs.join(', ')}`)
      } else {
        console.error('[Main] Migration failed:', result.error)
      }
    } else {
      console.log('[Main] No legacy data migration needed')
    }
  }

  // 执行数据库 schema 迁移（静默迁移）
  migrateDatabasesIfNeeded() {
    try {
      const { count } = checkMigrationNeeded()
      if (count > 0) {
        const result = migrateAllDatabases()
        if (!result.success) {
          console.error('[Main] Database schema migration failed:', result.error)
        }
      }
    } catch (error) {
      console.error('[Main] Error in migrateDatabasesIfNeeded:', error)
    }
  }

  // 创建主窗口
  async createWindow() {
    // 平台差异化窗口配置
    const windowOptions: Electron.BrowserWindowConstructorOptions = {
      width: 1180,
      height: 752,
      minWidth: 1180,
      minHeight: 752,
      show: false,
      autoHideMenuBar: true,
      webPreferences: {
        preload: join(__dirname, '../preload/index.js'),
        sandbox: false,
        devTools: true,
      },
    }

    // macOS: 使用 hiddenInset 保留红绿灯按钮
    // Windows: 使用 titleBarOverlay，在自定义标题栏区域右侧显示原生窗口按钮
    // Linux: 使用自定义标题栏和自定义按钮
    if (platform.isMacOS) {
      windowOptions.titleBarStyle = 'hiddenInset'
    } else if (platform.isWindows) {
      // 保留系统框架，只隐藏标题栏内容，把内容区域顶到最上方
      windowOptions.titleBarStyle = 'hidden'
      // 获取当前主题状态
      const isDark = nativeTheme.shouldUseDarkColors
      windowOptions.titleBarOverlay = {
        // 背景色与应用背景匹配，确保 hover 效果正确
        color: isDark ? '#111827' : '#f9fafb', // dark: gray-900, light: gray-50
        // 图标颜色适配主题
        symbolColor: isDark ? '#a1a1aa' : '#52525b', // dark: zinc-400, light: zinc-600
        height: 32,
      }
    } else {
      // Linux 继续使用无边框 + 自定义按钮
      windowOptions.frame = false
    }

    this.mainWindow = new BrowserWindow(windowOptions)

    this.mainWindow.once('ready-to-show', () => {
      this.mainWindow?.show()

      // Windows 上根据当前主题设置 titleBarOverlay 颜色
      if (platform.isWindows) {
        const isDark = nativeTheme.shouldUseDarkColors
        this.mainWindow?.setTitleBarOverlay({
          color: isDark ? '#111827' : '#f9fafb', // dark: gray-900, light: gray-50
          symbolColor: isDark ? '#a1a1aa' : '#52525b', // dark: zinc-400, light: zinc-600
          height: 32,
        })

        // 监听主题变化，动态更新颜色
        nativeTheme.on('updated', () => {
          if (this.mainWindow && platform.isWindows) {
            const isDark = nativeTheme.shouldUseDarkColors
            this.mainWindow.setTitleBarOverlay({
              color: isDark ? '#111827' : '#f9fafb', // dark: gray-900, light: gray-50
              symbolColor: isDark ? '#a1a1aa' : '#52525b', // dark: zinc-400, light: zinc-600
              height: 32,
            })
          }
        })
      }
    })

    // 主窗口事件
    this.mainWindowEvents()

    this.mainWindow.webContents.setWindowOpenHandler((details) => {
      shell.openExternal(details.url)
      return { action: 'deny' }
    })

    // HMR for renderer base on electron-vite cli.
    // Load the remote URL for development or the local html file for production.
    if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
      this.mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
    } else {
      this.mainWindow.loadFile(join(__dirname, '../../out/renderer/index.html'))
    }
  }

  // 主应用程序事件
  mainAppEvents() {
    app.whenReady().then(async () => {
      console.log('[Main] App is ready')
      // 设置Windows应用程序用户模型id
      if (process.platform === 'win32') app.setAppUserModelId(app.getName())

      // 记录日活（用于统计操作系统版本、客户端版本，便于更好的适配客户端）
      trackDailyActive()

      // 创建主窗口
      console.log('[Main] Creating window...')
      await this.createWindow()
      console.log('[Main] Window created')

      // 检查更新逻辑
      checkUpdate(this.mainWindow)

      // 引入主进程ipcMain
      if (this.mainWindow) {
        console.log('[Main] Registering IPC handlers...')
        mainIpcMain(this.mainWindow)
        console.log('[Main] IPC handlers registered')
      }

      // 开发环境下 F12 打开控制台
      app.on('browser-window-created', (_, window) => {
        optimizer.watchWindowShortcuts(window)
      })

      app.on('activate', () => {
        // 在 macOS 上，当单击 Dock 图标且没有其他窗口时，通常会重新创建窗口
        if (BrowserWindow.getAllWindows().length === 0) {
          this.createWindow()
          return
        }

        if (platform.isMacOS) {
          this.mainWindow?.show()
        }
      })

      // 监听渲染进程崩溃
      app.on('render-process-gone', (e, w, d) => {
        if (d.reason == 'crashed') {
          w.reload()
        }
        // fs.appendFile(`./error-log-${+new Date()}.txt`, `${new Date()}渲染进程被杀死${d.reason}\n`)
      })

      // 自定义协议
      app.on('open-url', (_, url) => {
        console.log('Received custom protocol URL:', url)
      })

      // 当所有窗口都关闭时退出应用，macOS 除外
      app.on('window-all-closed', () => {
        if (!platform.isMacOS) {
          app.quit()
        }
      })

      // 只有显式调用quit才退出系统，区分MAC系统程序坞退出和点击X隐藏
      app.on('before-quit', () => {
        // @ts-ignore
        app.isQuiting = true
      })

      // 退出前清理资源
      app.on('will-quit', () => {
        cleanup()
      })
    })
  }

  // 主窗口事件
  mainWindowEvents() {
    if (!this.mainWindow) {
      return
    }
    this.mainWindow.webContents.on('did-finish-load', () => {
      setTimeout(() => {
        this.mainWindow && this.mainWindow.webContents.send('app-started')
      }, 500)
    })

    this.mainWindow.on('maximize', () => {
      this.mainWindow?.webContents.send('windowState', true)
    })

    this.mainWindow.on('unmaximize', () => {
      this.mainWindow?.webContents.send('windowState', false)
    })

    // 窗口关闭
    this.mainWindow.on('close', (event) => {
      if (platform.isMacOS) {
        // macOS: 只有明确退出时才真正关闭，否则只隐藏窗口（符合 macOS 用户习惯）
        // @ts-ignore
        if (!app.isQuiting) {
          event.preventDefault()
          this.mainWindow?.hide()
        }
      }
      // Windows/Linux: 不阻止关闭，正常触发 window-all-closed → app.quit() → cleanup()
    })
  }
}

// 捕获未捕获的异常
process.on('uncaughtException', (error) => {
  console.error('Uncaught Exception:', error)
})

new MainProcess()
