import { Hype } from 'hype'
import { allApps, initApps, onChange, startApp, stopApp, updateAppIcon } from './apps'
import type { App as SharedApp } from '../shared/types'

const app = new Hype({ layout: false })

console.log('🐾 Toes!')
initApps()

// SSE endpoint for real-time app state updates
app.get('/api/apps/stream', c => {
  const encoder = new TextEncoder()

  const stream = new ReadableStream({
    start(controller) {
      const send = () => {
        // Strip proc field from apps before sending
        const apps: SharedApp[] = allApps().map(({ name, state, icon, error, port, started, logs }) => ({
          name,
          state,
          icon,
          error,
          port,
          started,
          logs,
        }))
        const data = JSON.stringify(apps)
        controller.enqueue(encoder.encode(`data: ${data}\n\n`))
      }

      // Send initial state
      send()

      // Subscribe to changes
      const unsub = onChange(send)

      // Handle client disconnect via abort signal
      c.req.raw.signal.addEventListener('abort', () => {
        unsub()
      })
    },
  })

  return new Response(stream, {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      Connection: 'keep-alive',
    },
  })
})

app.post('/api/apps/:app/start', c => {
  const appName = c.req.param('app')
  if (!appName) return c.json({ error: 'App not found' }, 404)

  startApp(appName)
  return c.json({ ok: true })
})

app.post('/api/apps/:app/restart', c => {
  const appName = c.req.param('app')
  if (!appName) return c.json({ error: 'App not found' }, 404)

  stopApp(appName)
  startApp(appName)
  return c.json({ ok: true })
})

app.post('/api/apps/:app/stop', c => {
  const appName = c.req.param('app')
  if (!appName) return c.json({ error: 'App not found' }, 404)

  stopApp(appName)
  return c.json({ ok: true })
})

app.post('/api/apps/:app/icon', c => {
  const appName = c.req.param('app')
  const icon = c.req.query('icon') ?? ''
  if (!icon) return c.json({ error: 'No icon query param provided' })

  try {
    updateAppIcon(appName, icon)
    return c.json({ ok: true })
  } catch (error) {
    return c.json({ error })
  }
})

export default app.defaults
