import { toString as qrToString } from 'qrcode'
import { generateToken, getActiveToken } from '../../rc/auth.js'
import { createRCPermissionCallbacks } from '../../rc/rcPermissionCallbacks.js'
import { setRCStreamSession } from '../../rc/rcStreamAdapter.js'
import { startRCServer, isRCServerRunning, getRCServerPort } from '../../rc/server.js'
import { registerSession } from '../../rc/sessionRegistry.js'
import { getTailscaleIP } from '../../rc/tailscale.js'
import type { LocalCommandCall } from '../../types/command.js'

const DEFAULT_PORT = 7390

async function makeQROutput(port: number, token: string): Promise<{ qr: string | null; host: string }> {
  const tsIP = await getTailscaleIP()
  const host = tsIP ?? 'localhost'
  const connectUrl = `http://${host}:${port}?token=${token}`
  const qr = await qrToString(connectUrl, {
    type: 'utf8',
    errorCorrectionLevel: 'L',
  }).catch(() => null)
  return { qr, host }
}

export const call: LocalCommandCall = async (_args, context) => {
  const cwd = process.cwd()
  const sessionId = `session-${Date.now()}`

  // If server is already running, just register this session
  if (isRCServerRunning()) {
    registerSession(sessionId, cwd)
    setRCStreamSession(sessionId)

    const rcCallbacks = createRCPermissionCallbacks(sessionId)
    context.setAppState(prev => ({
      ...prev,
      rcPermissionCallbacks: rcCallbacks,
    }))

    const port = getRCServerPort()
    const token = getActiveToken()!
    const { qr, host } = await makeQROutput(port, token)

    const lines = [
      '━━━ Remote Control ━━━',
      '',
      `Session registered: ${cwd}`,
      '',
      ...(qr ? [qr] : []),
      `Scan or open: ${host}:${port}`,
      '━━━━━━━━━━━━━━━━━━━━━━',
    ]

    return { type: 'text', value: lines.join('\n') }
  }

  // First time — start the server
  const token = generateToken()
  const port = DEFAULT_PORT

  try {
    await startRCServer({ port, host: '0.0.0.0', token })

    registerSession(sessionId, cwd)
    setRCStreamSession(sessionId)

    const rcCallbacks = createRCPermissionCallbacks(sessionId)
    context.setAppState(prev => ({
      ...prev,
      rcPermissionCallbacks: rcCallbacks,
    }))

    const { qr, host } = await makeQROutput(port, token)

    const lines = [
      '━━━ Remote Control ━━━',
      '',
      ...(qr ? [qr] : []),
      `Scan QR or open: ${host}:${port}`,
      '━━━━━━━━━━━━━━━━━━━━━━',
    ]

    return { type: 'text', value: lines.join('\n') }
  } catch (err) {
    return {
      type: 'text',
      value: `Failed to start RC server: ${err instanceof Error ? err.message : String(err)}`,
    }
  }
}
