import { BrowserWindow, dialog, ipcMain, type SaveDialogOptions } from 'electron'
import { writeFile } from 'fs/promises'
import JSZip from 'jszip'

import type { ExportClassFolderPayload, ExportClassFolderResponse } from '../types/classFolder'

const INVALID_FILENAME_CHARS = /[<>:"/\\|?*]/g

function sanitizeFolderName(name: string): string {
  return (
    name
      .replace(INVALID_FILENAME_CHARS, '_')
      .replaceAll(/./g, (char) => (char.charCodeAt(0) < 32 ? '_' : char))
      .trim() || '未命名班级'
  )
}

export function registerClassFolderIpc(): void {
  ipcMain.handle(
    'classes:export-empty-folder',
    async (event, payload: ExportClassFolderPayload): Promise<ExportClassFolderResponse> => {
      const className = payload.className.trim()

      if (!className) {
        return {
          ok: false,
          message: '请先填写班级名称'
        }
      }

      const safeClassId = sanitizeFolderName(payload.classId || className)
      const parentWindow = BrowserWindow.fromWebContents(event.sender)
      const dialogOptions: SaveDialogOptions = {
        title: '导出班级照片目录压缩包',
        defaultPath: `${safeClassId}.zip`,
        filters: [
          {
            name: 'ZIP 压缩包',
            extensions: ['zip']
          }
        ]
      }
      const result = parentWindow
        ? await dialog.showSaveDialog(parentWindow, dialogOptions)
        : await dialog.showSaveDialog(dialogOptions)

      if (result.canceled || !result.filePath) {
        return {
          ok: false,
          canceled: true,
          message: '已取消导出'
        }
      }

      const childNameCounts = new Map<string, number>()
      const zip = new JSZip()
      zip.folder(`${safeClassId}/`)

      try {
        for (const childName of payload.childNames) {
          const safeChildName = sanitizeFolderName(childName || '未命名幼儿')
          const nextCount = (childNameCounts.get(safeChildName) ?? 0) + 1
          childNameCounts.set(safeChildName, nextCount)

          const childFolderName = nextCount > 1 ? `${safeChildName}-${nextCount}` : safeChildName
          zip.folder(`${safeClassId}/${childFolderName}/`)
        }

        const zipContent = await zip.generateAsync({ type: 'nodebuffer' })
        await writeFile(result.filePath, zipContent)

        return {
          ok: true,
          zipPath: result.filePath,
          childFolderCount: payload.childNames.length
        }
      } catch (error) {
        const maybeNodeError = error as NodeJS.ErrnoException
        return {
          ok: false,
          message: maybeNodeError.message || '导出压缩包失败'
        }
      }
    }
  )
}
