import { NextRequest, NextResponse } from 'next/server'

const UNITY_BRIDGE_URL = process.env.UNITY_BRIDGE_URL || 'http://localhost:8090'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'

// Backend type for routing
type BackendType = 'unity' | 'python'

interface EndpointConfig {
  path: string
  backend: BackendType
  timeout?: number
}

// Python Backend endpoints for Unit System
const pythonEndpoints: Record<string, EndpointConfig> = {
  // Unit definitions
  'units-list': { path: '/api/units/definitions', backend: 'python' },
  'units-health': { path: '/api/units/health', backend: 'python' },
  // Analytics
  'analytics-overview': { path: '/api/analytics/dashboard/overview', backend: 'python' },
  'analytics-misconceptions': { path: '/api/analytics/misconceptions', backend: 'python' },
  // Teacher dashboard
  'teacher-dashboard': { path: '/api/teacher/dashboard', backend: 'python' },
  'teacher-units': { path: '/api/teacher/units/available', backend: 'python' },
}

// Streaming types
interface StreamStatusResponse {
  is_streaming: boolean
  frame_count: number
  width: number
  height: number
  quality: number
  uptime_seconds: string
}

interface StreamFrameResponse {
  success: boolean
  frame_count?: number
  width?: number
  height?: number
  data?: string // Base64 encoded JPEG
  message?: string
}

// Type definitions
interface BridgeStatus {
  status: string
  unity_version: string
  project: string
  scene: string
  is_playing: boolean
  is_compiling: boolean
  errors: number
  warnings: number
}

interface LogEntry {
  time: string
  type: string
  message: string
  frame: number
  stack?: string
}

interface LogsResponse {
  count: number
  total_errors: number
  total_warnings: number
  total_info: number
  logs: LogEntry[]
}

interface DiagnosticEntry {
  category: string
  severity: 'ok' | 'warning' | 'error'
  message: string
}

interface DiagnoseResponse {
  diagnostics: DiagnosticEntry[]
  errors: number
  warnings: number
}

/**
 * GET /api/admin/unity-bridge
 *
 * Proxy requests to the Unity AI Bridge running in the Unity Editor.
 *
 * Query Parameters:
 * - action: The endpoint to call (status, compile, logs, errors, warnings, scene, play, stop, quicksetup)
 * - limit: For logs, the number of entries to return (default: 50)
 * - name: For object endpoint, the name of the GameObject
 */
export async function GET(request: NextRequest) {
  const searchParams = request.nextUrl.searchParams
  const action = searchParams.get('action') || 'status'
  const limit = searchParams.get('limit') || '50'
  const objectName = searchParams.get('name')
  const unitId = searchParams.get('unit_id')
  const timeRange = searchParams.get('time_range') || 'month'

  // Check if this is a Python backend action
  if (pythonEndpoints[action]) {
    return handlePythonBackend(action, searchParams)
  }

  // Dynamic Python backend actions (with parameters)
  if (action === 'units-get' && unitId) {
    return fetchFromPython(`/api/units/definitions/${unitId}`)
  }
  if (action === 'analytics-learning-gain' && unitId) {
    return fetchFromPython(`/api/analytics/learning-gain/${unitId}?time_range=${timeRange}`)
  }
  if (action === 'analytics-stops' && unitId) {
    return fetchFromPython(`/api/analytics/unit/${unitId}/stops?time_range=${timeRange}`)
  }
  if (action === 'content-h5p' && unitId) {
    return fetchFromPython(`/api/units/content/${unitId}/h5p`)
  }
  if (action === 'content-worksheet' && unitId) {
    return fetchFromPython(`/api/units/content/${unitId}/worksheet`)
  }
  if (action === 'content-pdf' && unitId) {
    return fetchPdfFromPython(`/api/units/content/${unitId}/worksheet.pdf`)
  }

  // Map actions to Unity Bridge endpoints
  const endpointMap: Record<string, string> = {
    status: '/status',
    compile: '/compile',
    logs: `/logs?limit=${limit}`,
    errors: '/logs/errors',
    warnings: '/logs/warnings',
    scene: '/scene',
    selection: '/selection',
    play: '/play',
    stop: '/stop',
    quicksetup: '/quicksetup',
    // Streaming endpoints
    'stream-start': '/stream/start',
    'stream-stop': '/stream/stop',
    'stream-frame': '/stream/frame',
    'stream-status': '/stream/status',
  }

  // Handle screenshot endpoint - returns binary image data
  if (action === 'screenshot') {
    try {
      const response = await fetch(`${UNITY_BRIDGE_URL}/screenshot`, {
        headers: { 'Accept': 'image/jpeg' },
        signal: AbortSignal.timeout(5000),
      })

      if (!response.ok) {
        return NextResponse.json(
          { error: `Screenshot failed with status ${response.status}` },
          { status: response.status }
        )
      }

      const imageBuffer = await response.arrayBuffer()
      return new NextResponse(imageBuffer, {
        headers: {
          'Content-Type': 'image/jpeg',
          'Cache-Control': 'no-cache, no-store, must-revalidate',
        },
      })
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error'
      return NextResponse.json(
        { error: 'Screenshot fehlgeschlagen', details: errorMessage, offline: true },
        { status: 503 }
      )
    }
  }

  // Handle object endpoint separately (needs name parameter)
  let endpoint: string
  if (action === 'object' && objectName) {
    endpoint = `/object/${encodeURIComponent(objectName)}`
  } else {
    endpoint = endpointMap[action]
  }

  if (!endpoint) {
    return NextResponse.json(
      { error: 'Unknown action', validActions: Object.keys(endpointMap) },
      { status: 400 }
    )
  }

  try {
    const response = await fetch(`${UNITY_BRIDGE_URL}${endpoint}`, {
      headers: { 'Accept': 'application/json' },
      // Short timeout since it's localhost
      signal: AbortSignal.timeout(3000),
    })

    if (!response.ok) {
      return NextResponse.json(
        { error: `Unity Bridge returned ${response.status}`, offline: false },
        { status: response.status }
      )
    }

    const data = await response.json()
    return NextResponse.json(data)
  } catch (error) {
    // Distinguish between timeout and connection refused
    const errorMessage = error instanceof Error ? error.message : 'Unknown error'
    const isTimeout = errorMessage.includes('timeout') || errorMessage.includes('aborted')

    return NextResponse.json(
      {
        error: isTimeout
          ? 'Unity Bridge timed out - Unity might be busy'
          : 'Unity Bridge nicht erreichbar - Server in Unity starten',
        offline: true,
        details: errorMessage,
      },
      { status: 503 }
    )
  }
}

/**
 * POST /api/admin/unity-bridge
 *
 * Execute commands on the Unity Bridge.
 *
 * Query Parameters:
 * - action: The command to execute (diagnose, execute, clear-logs)
 *
 * For execute action, the body should contain:
 * - action: The execute action (select, setactive, delete, create, menu, log)
 * - name: GameObject name (for select, setactive, delete)
 * - active: true/false (for setactive)
 * - type: Object type (for create: cube, sphere, empty, etc.)
 * - path: Menu path (for menu action)
 * - message: Log message (for log action)
 */
export async function POST(request: NextRequest) {
  const searchParams = request.nextUrl.searchParams
  const action = searchParams.get('action')

  if (action === 'diagnose') {
    try {
      const response = await fetch(`${UNITY_BRIDGE_URL}/diagnose`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: '{}',
        // Diagnose can take longer
        signal: AbortSignal.timeout(10000),
      })

      if (!response.ok) {
        return NextResponse.json(
          { error: `Diagnose failed with status ${response.status}` },
          { status: response.status }
        )
      }

      const data: DiagnoseResponse = await response.json()
      return NextResponse.json(data)
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error'
      return NextResponse.json(
        { error: 'Diagnose fehlgeschlagen', details: errorMessage },
        { status: 503 }
      )
    }
  }

  if (action === 'execute') {
    let body: Record<string, unknown>
    try {
      body = await request.json()
    } catch {
      return NextResponse.json(
        { error: 'Invalid JSON body' },
        { status: 400 }
      )
    }

    // Validate required fields based on execute action
    const executeAction = body.action as string
    if (!executeAction) {
      return NextResponse.json(
        { error: 'Missing "action" field in body' },
        { status: 400 }
      )
    }

    try {
      const response = await fetch(`${UNITY_BRIDGE_URL}/execute`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
        signal: AbortSignal.timeout(5000),
      })

      if (!response.ok) {
        const errorData = await response.text()
        return NextResponse.json(
          { error: `Execute failed: ${errorData}` },
          { status: response.status }
        )
      }

      const data = await response.json()
      return NextResponse.json(data)
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error'
      return NextResponse.json(
        { error: 'Execute fehlgeschlagen', details: errorMessage },
        { status: 503 }
      )
    }
  }

  if (action === 'clear-logs') {
    try {
      const response = await fetch(`${UNITY_BRIDGE_URL}/logs/clear`, {
        method: 'GET', // Unity Bridge uses GET for clear
        signal: AbortSignal.timeout(3000),
      })

      const data = await response.json()
      return NextResponse.json(data)
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error'
      return NextResponse.json(
        { error: 'Clear logs fehlgeschlagen', details: errorMessage },
        { status: 503 }
      )
    }
  }

  return NextResponse.json(
    { error: 'Unknown POST action', validActions: ['diagnose', 'execute', 'clear-logs'] },
    { status: 400 }
  )
}

// ========================================
// Python Backend Helper Functions
// ========================================

/**
 * Handle requests to Python backend endpoints
 */
async function handlePythonBackend(
  action: string,
  searchParams: URLSearchParams
): Promise<NextResponse> {
  const config = pythonEndpoints[action]
  if (!config) {
    return NextResponse.json(
      { error: 'Unknown Python backend action' },
      { status: 400 }
    )
  }

  // Build query string from search params (excluding action)
  const queryParams = new URLSearchParams()
  searchParams.forEach((value, key) => {
    if (key !== 'action') {
      queryParams.set(key, value)
    }
  })
  const queryString = queryParams.toString()
  const url = queryString ? `${config.path}?${queryString}` : config.path

  return fetchFromPython(url, config.timeout)
}

/**
 * Fetch JSON from Python backend
 */
async function fetchFromPython(
  path: string,
  timeout: number = 5000
): Promise<NextResponse> {
  try {
    const response = await fetch(`${BACKEND_URL}${path}`, {
      headers: { 'Accept': 'application/json' },
      signal: AbortSignal.timeout(timeout),
    })

    if (!response.ok) {
      const errorText = await response.text()
      return NextResponse.json(
        { error: `Backend returned ${response.status}`, details: errorText },
        { status: response.status }
      )
    }

    const data = await response.json()
    return NextResponse.json(data)
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : 'Unknown error'
    const isTimeout = errorMessage.includes('timeout') || errorMessage.includes('aborted')

    return NextResponse.json(
      {
        error: isTimeout
          ? 'Backend timed out'
          : 'Backend nicht erreichbar - Server starten mit: cd backend && python main.py',
        offline: true,
        details: errorMessage,
      },
      { status: 503 }
    )
  }
}

/**
 * Fetch PDF from Python backend
 */
async function fetchPdfFromPython(path: string): Promise<NextResponse> {
  try {
    const response = await fetch(`${BACKEND_URL}${path}`, {
      headers: { 'Accept': 'application/pdf' },
      signal: AbortSignal.timeout(15000), // PDF generation can take longer
    })

    if (!response.ok) {
      return NextResponse.json(
        { error: `PDF generation failed with status ${response.status}` },
        { status: response.status }
      )
    }

    const pdfBuffer = await response.arrayBuffer()
    return new NextResponse(pdfBuffer, {
      headers: {
        'Content-Type': 'application/pdf',
        'Content-Disposition': 'attachment; filename="worksheet.pdf"',
      },
    })
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : 'Unknown error'
    return NextResponse.json(
      { error: 'PDF generation fehlgeschlagen', details: errorMessage },
      { status: 503 }
    )
  }
}
