import { app, clipboard, dialog, ipcMain, nativeImage, shell, BrowserWindow } from 'electron'
import type { NativeImage } from 'electron'
import { exec } from 'child_process'
import { dirname, join } from 'path'
import {
  closeScreen,
  closeAllScreens,
  listScreens,
  publishScreen,
  setPages,
  startCarousel,
  startInteractive,
  stopCarousel,
  stopCarouselAuto,
  mainScreenIndex,
  publishMain,
  restoreMain,
  probeScreens,
  setKeyLock,
  isKeyLocked
} from './screens'
import type { CarouselPage } from './screens'
import { loadSettings, saveSettings } from './settings'
import type { AppSettings } from './settings'
import { readProjectFile, writeProjectFile } from './project'
import { createDesktopShortcut, chooseProjectFile } from './shortcuts'
import type { ShortcutKind } from './shortcuts'
import { consumePendingLoad } from './loader'

function beepSystem(): void {
  if (process.platform === 'darwin') {
    shell.beep()
    return
  }
  // Windows / Linux：调用系统终端提示音
  exec('powershell -NoProfile -NonInteractive -Command "[console]::beep(880,400)"', () => undefined)
}

/** 截图压缩为 JPEG dataURL，保证体积不超过 maxBytes（默认 500KB）：先降质量，再逐步缩小尺寸 */
function compressSnapshot(img: NativeImage, maxBytes = 500 * 1024): string {
  let cur = img
  const fit = (side: number): void => {
    const { width, height } = cur.getSize()
    const maxSide = Math.max(width, height)
    if (maxSide > side) {
      const k = side / maxSide
      cur = cur.resize({ width: Math.max(1, Math.round(width * k)), height: Math.max(1, Math.round(height * k)) })
    }
  }
  const toData = (q: number): { buf: Buffer; url: string } => {
    const buf = cur.toJPEG(q)
    return { buf, url: 'data:image/jpeg;base64,' + buf.toString('base64') }
  }
  fit(1600)
  for (const q of [80, 65, 50, 35]) {
    const { buf, url } = toData(q)
    if (buf.length <= maxBytes) return url
  }
  for (const side of [1280, 960, 640, 480]) {
    fit(side)
    for (const q of [60, 45, 30]) {
      const { buf, url } = toData(q)
      if (buf.length <= maxBytes) return url
    }
  }
  return toData(25).url
}

export function registerIpc(): void {
  // ===== 剪贴板写入（主进程 clipboard 保证可靠，渲染层 navigator.clipboard 易受权限/焦点影响） =====
  ipcMain.handle('clipboard:write', (_e, text: string): void => {
    clipboard.writeText(String(text ?? ''))
  })

  // ===== 系统浏览器打开外部链接 =====
  ipcMain.handle('shell:openExternal', (_e, url: string): Promise<void> => shell.openExternal(url))

  // ===== 窗口控制 =====
  ipcMain.on('win:minimize', () => BrowserWindow.getFocusedWindow()?.minimize())
  ipcMain.on('win:toggle-maximize', () => {
    const w = BrowserWindow.getFocusedWindow()
    if (!w) return
    if (w.isMaximized()) w.unmaximize()
    else w.maximize()
  })
  ipcMain.on('win:close', () => BrowserWindow.getFocusedWindow()?.close())

  // ===== 屏幕 / 多屏发布 =====
  ipcMain.handle('screens:list', () => listScreens())
  ipcMain.handle('screens:states', () => listScreens())
  ipcMain.handle(
    'screen:publish',
    (_e, payload: { index: number; url: string; title: string; navDisabled?: boolean }) =>
      publishScreen(payload.index, payload.url, payload.title, { navDisabled: payload.navDisabled })
  )
  ipcMain.handle('screen:close', (_e, index: number) => closeScreen(index))
  ipcMain.handle('screen:closeAll', () => {
    closeAllScreens()
    return listScreens()
  })
  ipcMain.handle('screens:mainIndex', () => mainScreenIndex())
  ipcMain.handle('screen:publishMain', (_e, payload: { url: string; title: string }) =>
    publishMain(payload.url, payload.title)
  )
  ipcMain.handle('screen:restoreMain', () => restoreMain())
  ipcMain.handle('screens:probe', () => probeScreens())

  // ===== 单屏轮播 =====
  ipcMain.handle(
    'carousel:start',
    (_e, payload: { index: number; pages: CarouselPage[]; intervalSec?: number }) =>
      startCarousel(payload.index, payload.pages, payload.intervalSec ?? 0)
  )
  ipcMain.handle(
    'carousel:startInteractive',
    (_e, req: { mainIndex: number; pagesByScreen: Record<number, { url: string; title: string }[]> }) =>
      startInteractive(req)
  )
  ipcMain.handle('carousel:stop', (_e, index: number) => stopCarousel(index))
  ipcMain.handle('carousel:stopAuto', (_e, index: number) => stopCarouselAuto(index))

  // 渲染层页面同步（用于屏幕键盘切页）
  ipcMain.on('project:sync', (_e, pages: unknown) => {
    setPages(
      Array.isArray(pages)
        ? pages.map((p) => p as { id: string; title: string; url: string; screen: number; ctrl: number; display: boolean })
        : []
    )
  })

  // ===== 工程文件（带 JSON 读写密码）=====
  /** 记住用户最后一次选择/保存工程的文件夹 */
  const rememberDir = async (p: string): Promise<void> => {
    try {
      await saveSettings({ lastDir: dirname(p) })
    } catch {
      // 记录失败不影响主流程
    }
  }

  ipcMain.handle('project:saveAs', async (_e, payload: { data: string; password?: string }) => {
    const settings = await loadSettings()
    const pwd = payload.password ?? settings.jsonPassword
    const defaultPath = settings.lastDir
      ? join(settings.lastDir, settings.projectName + '.json')
      : settings.projectName + '.json'
    const r = await dialog.showSaveDialog({
      title: '保存工程文件',
      defaultPath,
      filters: [{ name: 'JSON 工程文件', extensions: ['json'] }]
    })
    if (r.canceled || !r.filePath) return null
    const res = await writeProjectFile(r.filePath, payload.data, pwd)
    if (res.ok) await rememberDir(r.filePath)
    return res.ok ? r.filePath : null
  })

  ipcMain.handle('project:save', async (_e, payload: { path: string; data: string; password?: string }) => {
    if (!payload.path) return null
    const settings = await loadSettings()
    const pwd = payload.password ?? settings.jsonPassword
    const res = await writeProjectFile(payload.path, payload.data, pwd)
    return res.ok ? payload.path : null
  })

  // 打开工程：先弹框选文件，用当前配置密码尝试解密
  ipcMain.handle('project:open', async (_e, password?: string) => {
    const settings = await loadSettings()
    const r = await dialog.showOpenDialog({
      title: '打开工程文件',
      defaultPath: settings.lastDir || undefined,
      filters: [{ name: 'JSON 工程文件', extensions: ['json'] }],
      properties: ['openFile']
    })
    if (r.canceled || !r.filePaths[0]) return null
    const pwd = password ?? settings.jsonPassword
    const res = await readProjectFile(r.filePaths[0], pwd)
    await rememberDir(r.filePaths[0])
    return res
  })

  // 打开指定路径工程（用于密码输入重试 / 快捷方式场景）
  ipcMain.handle('project:openAt', (_e, payload: { path: string; password?: string }) =>
    readProjectFile(payload.path, payload.password ?? '')
  )

  // ===== 应用设置 =====
  ipcMain.handle('settings:get', () => loadSettings())
  ipcMain.handle('settings:set', (_e, patch: Partial<AppSettings>) => saveSettings(patch))

  // ===== 应用信息 / 启动加载 =====
  ipcMain.handle('app:info', () => ({
    appVersion: app.getVersion(),
    electron: process.versions.electron,
    chrome: process.versions.chrome,
    node: process.versions.node,
    platform: process.platform + ' ' + process.arch
  }))
  ipcMain.handle('app:consumeLoad', () => consumePendingLoad())

  // ===== 页面截图（预览图）=====
  // 预览 webview 截图 → PNG Buffer → 主进程压缩为 ≤500KB 的 JPEG dataURL
  ipcMain.handle('page:compress', (_e, png: Uint8Array) => {
    try {
      const img = nativeImage.createFromBuffer(Buffer.from(png))
      if (img.isEmpty()) return null
      return compressSnapshot(img)
    } catch {
      return null
    }
  })
  ipcMain.handle('page:snapshot', async (_e, url: string) => {
    if (!url || url === 'about:blank') return null
    const win = new BrowserWindow({
      width: 1280,
      height: 720,
      show: false,
      frame: false,
      webPreferences: {
        contextIsolation: true,
        nodeIntegration: false,
        sandbox: false,
        spellcheck: false
      }
    })
    try {
      win.webContents.setWindowOpenHandler(() => ({ action: 'deny' }))
      await win.loadURL(url)
      // 等待页面渲染完成（图表/动画）
      await new Promise((r) => setTimeout(r, 1600))
      const img = await win.webContents.capturePage()
      if (img.isEmpty()) return null
      return compressSnapshot(img)
    } catch {
      return null
    } finally {
      if (!win.isDestroyed()) win.destroy()
    }
  })

  // ===== 页面元信息提取（标题/描述）=====
  ipcMain.handle('page:fetchMeta', async (_e, url: string) => {
    if (!url || !/^https?:\/\//i.test(url)) return null
    const win = new BrowserWindow({
      width: 1280,
      height: 720,
      show: false,
      frame: false,
      webPreferences: {
        contextIsolation: true,
        nodeIntegration: false,
        sandbox: false,
        spellcheck: false
      }
    })
    try {
      win.webContents.setWindowOpenHandler(() => ({ action: 'deny' }))
      // 加载超时保护（12s），防止不可达 URL 长时间挂起
      const loadP = win.loadURL(url).catch(() => {})
      await Promise.race([
        loadP,
        new Promise<void>((_, rej) => setTimeout(() => rej(new Error('load timeout')), 12000))
      ])
      // 轮询等待动态 JS 设置标题（最长 2s），防止 title 为空
      for (let i = 0; i < 8; i++) {
        const t: unknown = await win.webContents.executeJavaScript('document.title')
        if (typeof t === 'string' && t.trim()) break
        await new Promise((r) => setTimeout(r, 250))
      }
      const meta = (await win.webContents.executeJavaScript(`(() => {
        const d = document.querySelector('meta[name="description"]')
          || document.querySelector('meta[property="og:description"]')
        return {
          title: (document.title || '').trim(),
          desc: d ? (d.getAttribute('content') || '').trim() : ''
        }
      })()`)) as { title?: unknown; desc?: unknown }
      if (!meta || typeof meta !== 'object') return null
      return {
        title: typeof meta.title === 'string' ? meta.title : '',
        desc: typeof meta.desc === 'string' ? meta.desc : ''
      }
    } catch {
      return null
    } finally {
      if (!win.isDestroyed()) win.destroy()
    }
  })

  // ===== 对话框 =====
  ipcMain.handle('dialog:confirm', async (_e, message: string) => {
    const r = await dialog.showMessageBox({
      type: 'question',
      title: '智慧农业大数据可视化控制中心',
      message,
      buttons: ['确定', '取消'],
      defaultId: 0,
      cancelId: 1
    })
    return r.response === 0
  })

  // ===== 工具 =====
  ipcMain.handle('beep', () => {
    beepSystem()
  })

  // 旧接口兼容：直接打开本工具
  ipcMain.handle('desktop:shortcut', () => createDesktopShortcut('app').ok)

  // 三类快捷方式；edit/publish 时先在主进程弹框选择工程文件
  ipcMain.handle('shortcut:create', async (_e, kind: ShortcutKind) => {
    if (kind === 'app') return createDesktopShortcut('app')
    const path = await chooseProjectFile()
    if (!path) return { ok: false, message: '未选择工程文件' }
    return createDesktopShortcut(kind, path)
  })

  // ===== 快捷键锁定（遥控设置）=====
  ipcMain.handle('screens:keyLock', (_e, locked: boolean) => setKeyLock(!!locked))
  ipcMain.handle('screens:keyLockState', () => isKeyLocked())

  // ===== 窗口关闭守卫（未保存提示）=====
  ipcMain.on('window:dirty', (_e, d: boolean) => {
    setDirtyFlag(!!d)
  })
}

let dirty = false
let forceQuit = false

function setDirtyFlag(d: boolean): void {
  dirty = d
}

export function installCloseGuard(win: BrowserWindow): void {
  win.on('close', (e) => {
    if (forceQuit) return
    e.preventDefault()
    const warn = dirty ? '当前工程有未保存的修改。\n\n' : ''
    void dialog
      .showMessageBox(win, {
        type: 'warning',
        title: '确认退出',
        message: `${warn}确定要退出智慧农业大数据可视化控制中心吗？`,
        buttons: ['退出', '取消'],
        defaultId: 1,
        cancelId: 1
      })
      .then((r) => {
        if (r.response === 0) {
          forceQuit = true
          // 先关闭所有播放中的子页面（屏幕窗体/轮播/探测/主屏播放），再关闭主窗口
          closeAllScreens()
          win.close()
        }
      })
  })
}
