import { jsonResponse, errorResponse } from '../utils/cors'
import { PORT_TERMINAL } from '../config'

interface PermissionPayload {
  hook_event_name?: string
  session_id?: string
  tool_name?: string
  tool_input?: unknown
  cwd?: string
  [key: string]: unknown
}

interface PendingPermission {
  resolve: (decision: string) => void
  timer: ReturnType<typeof setTimeout>
  payload: PermissionPayload
}

// Map of requestId -> pending permission promise resolver
const pendingPermissions = new Map<string, PendingPermission>()

const PERMISSION_TIMEOUT_MS = 60_000

export async function handleClaudePermission(req: Request): Promise<Response | null> {
  if (req.method !== 'POST') return null

  try {
    const body = await req.json() as PermissionPayload
    const requestId = `perm_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`

    // Broadcast permission request to UI via WebSocket
    try {
      await fetch(`http://localhost:${PORT_TERMINAL}/claude-permission`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ requestId, ...body })
      })
    } catch (e) {
      console.error('[claude-permission] Failed to broadcast to terminal server:', e)
    }

    // Also broadcast claude-status for backward compat (animations)
    try {
      await fetch(`http://localhost:${PORT_TERMINAL}/claude-status`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ status: 'permissionRequest', tool: body.tool_name })
      })
    } catch (e) {
      console.error('[claude-permission] Failed to forward status:', e)
    }

    // Wait for UI decision (or timeout)
    const decision = await new Promise<string>((resolve) => {
      const timer = setTimeout(() => {
        pendingPermissions.delete(requestId)
        resolve('ask')
      }, PERMISSION_TIMEOUT_MS)

      pendingPermissions.set(requestId, { resolve, timer, payload: body })
    })

    return jsonResponse({ decision, requestId })
  } catch (e) {
    return errorResponse('Invalid JSON body', 400)
  }
}

export async function handleClaudePermissionRespond(req: Request): Promise<Response | null> {
  if (req.method !== 'POST') return null

  try {
    const body = await req.json() as { requestId: string, decision: 'allow' | 'deny' }

    if (!body.requestId || !body.decision) {
      return errorResponse('Missing requestId or decision', 400)
    }

    if (!['allow', 'deny'].includes(body.decision)) {
      return errorResponse('Decision must be "allow" or "deny"', 400)
    }

    const pending = pendingPermissions.get(body.requestId)
    if (!pending) {
      return errorResponse('Permission request not found or already expired', 404)
    }

    // Resolve the pending promise
    clearTimeout(pending.timer)
    pendingPermissions.delete(body.requestId)
    pending.resolve(body.decision)

    return jsonResponse({ success: true, requestId: body.requestId, decision: body.decision })
  } catch (e) {
    return errorResponse('Invalid JSON body', 400)
  }
}

// List pending permissions (useful for UI to recover state)
export async function handleClaudePermissionList(req: Request): Promise<Response | null> {
  if (req.method !== 'GET') return null

  const pending = Array.from(pendingPermissions.entries()).map(([id, p]) => ({
    requestId: id,
    tool_name: p.payload.tool_name,
    tool_input: p.payload.tool_input,
    session_id: p.payload.session_id
  }))

  return jsonResponse({ pending })
}
