import { NextRequest, NextResponse } from 'next/server'
import { getDatabase } from '@/lib/db'
import { requireRole } from '@/lib/auth'
import { readLimiter } from '@/lib/rate-limit'
import { logger } from '@/lib/logger'
import { getSecurityPosture } from '@/lib/security-events'
import { getMcpCallStats } from '@/lib/mcp-audit'
import { runSecurityScan } from '@/lib/security-scan'

type Timeframe = 'hour' | 'day' | 'week' | 'month'

const TIMEFRAME_SECONDS: Record<Timeframe, number> = {
  hour: 3600,
  day: 86400,
  week: 7 * 86400,
  month: 30 * 86400,
}

export async function GET(request: NextRequest) {
  const auth = requireRole(request, 'admin')
  if ('error' in auth) return NextResponse.json({ error: auth.error }, { status: auth.status })

  const rateCheck = readLimiter(request)
  if (rateCheck) return rateCheck

  try {
    const { searchParams } = new URL(request.url)
    const timeframe = (searchParams.get('timeframe') || 'day') as Timeframe
    const eventTypeFilter = searchParams.get('event_type')
    const severityFilter = searchParams.get('severity')
    const agentFilter = searchParams.get('agent')
    const workspaceId = auth.user.workspace_id ?? 1

    const seconds = TIMEFRAME_SECONDS[timeframe] || TIMEFRAME_SECONDS.day
    const since = Math.floor(Date.now() / 1000) - seconds
    const db = getDatabase()

    // Infrastructure scan (same as onboarding security scan)
    const scan = runSecurityScan()

    // Event-based posture (incidents, trust scores)
    const eventPosture = getSecurityPosture(workspaceId)

    // Blend: weighted average — 70% infrastructure config, 30% event history
    const blendedScore = Math.round(scan.score * 0.7 + eventPosture.score * 0.3)
    const level = blendedScore >= 90 ? 'hardened'
      : blendedScore >= 70 ? 'secure'
      : blendedScore >= 40 ? 'needs-attention'
      : 'at-risk'

    // Auth events
    const authEventsQuery = db.prepare(`
      SELECT event_type, severity, agent_name, detail, ip_address, created_at
      FROM security_events
      WHERE workspace_id = ? AND created_at > ?
        AND event_type IN ('auth.failure', 'auth.token_rotation', 'auth.access_denied')
      ORDER BY created_at DESC
      LIMIT 50
    `).all(workspaceId, since) as any[]

    const loginFailures = authEventsQuery.filter(e => e.event_type === 'auth.failure').length
    const tokenRotations = authEventsQuery.filter(e => e.event_type === 'auth.token_rotation').length
    const accessDenials = authEventsQuery.filter(e => e.event_type === 'auth.access_denied').length

    // Agent trust
    const agents = db.prepare(`
      SELECT agent_name, trust_score, last_anomaly_at,
        auth_failures + injection_attempts + rate_limit_hits + secret_exposures as anomalies
      FROM agent_trust_scores
      WHERE workspace_id = ?
      ORDER BY trust_score ASC
    `).all(workspaceId) as any[]

    const flaggedCount = agents.filter((a: any) => a.trust_score < 0.8).length

    // Secret exposures
    const secretEvents = db.prepare(`
      SELECT event_type, severity, agent_name, detail, created_at
      FROM security_events
      WHERE workspace_id = ? AND created_at > ? AND event_type = 'secret.exposure'
      ORDER BY created_at DESC
      LIMIT 20
    `).all(workspaceId, since) as any[]

    // MCP audit summary
    const mcpTotals = db.prepare(`
      SELECT
        COUNT(*) as total_calls,
        COUNT(DISTINCT tool_name) as unique_tools,
        SUM(CASE WHEN success = 0 THEN 1 ELSE 0 END) as failures
      FROM mcp_call_log
      WHERE workspace_id = ? AND created_at > ?
    `).get(workspaceId, since) as any

    const topTools = db.prepare(`
      SELECT tool_name, COUNT(*) as count
      FROM mcp_call_log
      WHERE workspace_id = ? AND created_at > ?
      GROUP BY tool_name
      ORDER BY count DESC
      LIMIT 10
    `).all(workspaceId, since) as any[]

    const totalCalls = mcpTotals?.total_calls ?? 0
    const failureRate = totalCalls > 0
      ? Math.round(((mcpTotals?.failures ?? 0) / totalCalls) * 10000) / 100
      : 0

    // Rate limit hits
    const rateLimitEvents = db.prepare(`
      SELECT COUNT(*) as total
      FROM security_events
      WHERE workspace_id = ? AND created_at > ? AND event_type = 'rate_limit.hit'
    `).get(workspaceId, since) as any

    const rateLimitByIp = db.prepare(`
      SELECT ip_address, COUNT(*) as count
      FROM security_events
      WHERE workspace_id = ? AND created_at > ? AND event_type = 'rate_limit.hit' AND ip_address IS NOT NULL
      GROUP BY ip_address
      ORDER BY count DESC
      LIMIT 10
    `).all(workspaceId, since) as any[]

    // Injection attempts
    const injectionEvents = db.prepare(`
      SELECT event_type, severity, agent_name, detail, ip_address, created_at
      FROM security_events
      WHERE workspace_id = ? AND created_at > ? AND event_type = 'injection.attempt'
      ORDER BY created_at DESC
      LIMIT 20
    `).all(workspaceId, since) as any[]

    // Timeline (bucketed by hour)
    const bucketSize = timeframe === 'hour' ? 300 : 3600
    let timelineQuery = `
      SELECT
        (created_at / ${bucketSize}) * ${bucketSize} as bucket,
        COUNT(*) as event_count,
        MAX(CASE WHEN severity = 'critical' THEN 3 WHEN severity = 'warning' THEN 2 ELSE 1 END) as max_severity
      FROM security_events
      WHERE workspace_id = ? AND created_at > ?
    `
    const timelineParams: any[] = [workspaceId, since]

    if (eventTypeFilter) {
      timelineQuery += ' AND event_type = ?'
      timelineParams.push(eventTypeFilter)
    }
    if (severityFilter) {
      timelineQuery += ' AND severity = ?'
      timelineParams.push(severityFilter)
    }
    if (agentFilter) {
      timelineQuery += ' AND agent_name = ?'
      timelineParams.push(agentFilter)
    }

    timelineQuery += ' GROUP BY bucket ORDER BY bucket ASC'

    const timeline = db.prepare(timelineQuery).all(...timelineParams) as any[]

    const severityMap: Record<number, string> = { 3: 'critical', 2: 'warning', 1: 'info' }

    return NextResponse.json({
      posture: { score: blendedScore, level },
      scan: {
        score: scan.score,
        overall: scan.overall,
        categories: scan.categories,
      },
      authEvents: {
        loginFailures,
        tokenRotations,
        accessDenials,
        recentEvents: authEventsQuery.slice(0, 10),
      },
      agentTrust: {
        agents: agents.map((a: any) => ({
          name: a.agent_name,
          score: Math.round(a.trust_score * 100) / 100,
          anomalies: a.anomalies,
        })),
        flaggedCount,
      },
      secretExposures: {
        total: secretEvents.length,
        recent: secretEvents.slice(0, 5),
      },
      mcpAudit: {
        totalCalls,
        uniqueTools: mcpTotals?.unique_tools ?? 0,
        failureRate,
        topTools: topTools.map((t: any) => ({ name: t.tool_name, count: t.count })),
      },
      rateLimits: {
        totalHits: rateLimitEvents?.total ?? 0,
        byIp: rateLimitByIp.map((r: any) => ({ ip: r.ip_address, count: r.count })),
      },
      injectionAttempts: {
        total: injectionEvents.length,
        recent: injectionEvents.slice(0, 5),
      },
      timeline: timeline.map((t: any) => ({
        timestamp: t.bucket,
        eventCount: t.event_count,
        severity: severityMap[t.max_severity] || 'info',
      })),
    })
  } catch (error) {
    logger.error({ err: error }, 'GET /api/security-audit error')
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
  }
}
