import { spawn } from 'node:child_process'
import { watch } from 'node:fs'
import { createRequire } from 'node:module'
import { resolve } from 'node:path'

const require = createRequire(import.meta.url)
const electronPath = require('electron')

let child = null
let stopping = false
let restartTimer = null

function start() {
  child = spawn(electronPath, ['--import', 'tsx', 'src/server/index.ts'], {
    env: {
      ...process.env,
      ELECTRON_RUN_AS_NODE: '1',
      GROWTH_REPORT_USER_DATA: process.env.GROWTH_REPORT_USER_DATA || '.electron-dev-data'
    },
    stdio: 'inherit',
    windowsHide: true
  })

  child.once('exit', (code, signal) => {
    child = null

    if (stopping) {
      process.exit(0)
    }

    if (signal) {
      process.kill(process.pid, signal)
      return
    }

    process.exit(code ?? 0)
  })
}

function stop(signal = 'SIGTERM') {
  if (child && !child.killed) {
    child.kill(signal)
  }
}

function scheduleRestart() {
  if (stopping) {
    return
  }

  clearTimeout(restartTimer)
  restartTimer = setTimeout(() => {
    if (!child) {
      start()
      return
    }

    const currentChild = child
    currentChild.once('exit', () => {
      if (!stopping) {
        start()
      }
    })
    currentChild.kill('SIGTERM')
  }, 150)
}

function shutdown(signal = 'SIGTERM') {
  if (stopping) {
    return
  }

  stopping = true
  clearTimeout(restartTimer)
  stop(signal)
}

start()

const watchedRoots = ['src/server', 'src/main/services', 'src/main/entities', 'src/main/types']

for (const root of watchedRoots) {
  watch(resolve(root), { recursive: true }, scheduleRestart)
}

process.once('SIGINT', () => shutdown('SIGINT'))
process.once('SIGTERM', () => shutdown('SIGTERM'))
process.once('exit', () => stop())
