import { NextRequest, NextResponse } from 'next/server'
import { readFile, readdir } from 'fs/promises'
import { exec } from 'child_process'
import { promisify } from 'util'

const execAsync = promisify(exec)
const CEO_PIN = process.env.CEO_PIN || '5050'

interface AgentStatus {
  status: string
  role: string
  port: number
  workspace: string
  task: string | null
  last_heartbeat: string | null
  progress: number | null
  blocked_on: string | null
}

interface FleetState {
  version: number
  timestamp: string
  cycle: number
  agents: Record<string, AgentStatus>
  tasks: {
    in_progress: Array<{ id: string; title: string; assigned_to: string; started: string; priority: string }>
    blocked: Array<{ id: string; title: string; blocked_reason?: string }>
    backlog: Array<{ id: string; title: string; priority: string }>
  }
  alerts: Array<{ type: string; agent?: string; message: string; detected_at?: string }>
  decisions_needed: Array<{ from: string; description: string; requested_at: string }>
}

interface JsonlEntry {
  ts?: string
  timestamp?: string
  from?: string
  subject?: string
  body?: string
  priority?: string
  category?: string
  summary?: string
  detail?: string | null
  requested_at?: string
  description?: string
}

function asIsoOrNow(value?: string): string {
  if (!value) return new Date().toISOString()
  const d = new Date(value)
  return Number.isNaN(d.getTime()) ? new Date().toISOString() : d.toISOString()
}

async function readJsonl(path: string, limit = 200): Promise<JsonlEntry[]> {
  try {
    const raw = await readFile(path, 'utf8')
    const lines = raw.split('\n').filter(Boolean).slice(-limit)
    const out: JsonlEntry[] = []
    for (const line of lines) {
      try {
        out.push(JSON.parse(line))
      } catch {
        // skip malformed line
      }
    }
    return out
  } catch {
    return []
  }
}

async function getSystemHealth() {
  try {
    const [cpuResult, memResult, diskResult, uptimeResult] = await Promise.all([
      execAsync("top -bn1 | grep 'Cpu(s)' | awk '{print $2}'").catch(() => ({ stdout: '0' })),
      execAsync("free -m | awk 'NR==2{printf \"%s %s %.0f\", $3, $2, $3*100/$2}'").catch(() => ({ stdout: '0 0 0' })),
      execAsync("df -h / | awk 'NR==2{printf \"%s %s %s\", $3, $2, $5}'").catch(() => ({ stdout: '0 0 0%' })),
      execAsync('uptime -p').catch(() => ({ stdout: 'unknown' })),
    ])

    const memParts = memResult.stdout.trim().split(' ')
    const diskParts = diskResult.stdout.trim().split(' ')

    return {
      cpu: `${parseFloat(cpuResult.stdout.trim()).toFixed(1)}%`,
      memory: {
        used: `${memParts[0]}MB`,
        total: `${memParts[1]}MB`,
        percent: parseInt(memParts[2]) || 0,
      },
      disk: {
        used: diskParts[0],
        total: diskParts[1],
        percent: parseInt(diskParts[2]) || 0,
      },
      uptime: uptimeResult.stdout.trim(),
    }
  } catch {
    return {
      cpu: 'N/A',
      memory: { used: 'N/A', total: 'N/A', percent: 0 },
      disk: { used: 'N/A', total: 'N/A', percent: 0 },
      uptime: 'N/A',
    }
  }
}

async function getAppHealth() {
  const start = Date.now()
  try {
    const res = await fetch('http://localhost:3000', { signal: AbortSignal.timeout(5000) })
    return { status: res.ok ? 'healthy' : 'degraded', responseMs: Date.now() - start }
  } catch {
    return { status: 'down', responseMs: Date.now() - start }
  }
}

async function getGrowthEngineHealth() {
  const start = Date.now()
  try {
    const res = await fetch('https://rateright-growth-production.up.railway.app/api/health', {
      signal: AbortSignal.timeout(5000),
    })
    return { status: res.ok ? 'healthy' : 'degraded', responseMs: Date.now() - start }
  } catch {
    return { status: 'down', responseMs: Date.now() - start }
  }
}

function isToday(iso: string): boolean {
  const d = new Date(iso)
  const now = new Date()
  return d.getUTCFullYear() === now.getUTCFullYear() && d.getUTCMonth() === now.getUTCMonth() && d.getUTCDate() === now.getUTCDate()
}

export async function GET(request: NextRequest) {
  const pin = request.nextUrl.searchParams.get('pin')
  if (pin !== CEO_PIN) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })

  try {
    let fleetState: FleetState | null = null
    try {
      const raw = await readFile('/home/ccuser/shared/fleet-state.json', 'utf8')
      fleetState = JSON.parse(raw)
    } catch {
      fleetState = null
    }

    const [systemHealth, appHealth, growthHealth, bulletins, decisions, currentMd, kanbanMd, roadmapMd] = await Promise.all([
      getSystemHealth(),
      getAppHealth(),
      getGrowthEngineHealth(),
      readJsonl('/home/ccuser/shared/fleet-bulletins.jsonl', 300),
      readJsonl('/home/ccuser/shared/decisions.jsonl', 150),
      readFile('/home/ccuser/shared/CURRENT.md', 'utf8').catch(() => ''),
      readFile('/home/ccuser/shared/KANBAN.md', 'utf8').catch(() => ''),
      readFile('/home/ccuser/shared/ROADMAP.md', 'utf8').catch(() => ''),
    ])

    const inboxDir = '/home/ccuser/shared/inboxes'
    let inboxApprovals: Array<{ source: string; subject: string; summary: string; ts: string }> = []
    let trackEvents: Array<{ ts: string; type: string; source: string; summary: string }> = []

    try {
      const files = (await readdir(inboxDir)).filter((f) => f.endsWith('.jsonl'))
      const inboxSets = await Promise.all(files.map((f) => readJsonl(`${inboxDir}/${f}`, 120)))
      for (let i = 0; i < files.length; i++) {
        const source = files[i].replace('.jsonl', '')
        for (const e of inboxSets[i]) {
          const ts = asIsoOrNow(e.ts || e.timestamp)
          const text = `${e.subject || ''} ${e.body || ''}`.toLowerCase()
          if (text.includes('approve') || text.includes('approval') || text.includes('need michael') || text.includes('decision')) {
            inboxApprovals.push({
              source,
              subject: e.subject || 'Approval item',
              summary: (e.body || '').slice(0, 240),
              ts,
            })
          }
          if (isToday(ts)) {
            trackEvents.push({
              ts,
              type: 'inbox',
              source,
              summary: `${e.subject || 'Message'}${e.from ? ` (from ${e.from})` : ''}`,
            })
          }
        }
      }
    } catch {
      // ignore inbox read failures
    }

    const approvals = [
      ...(fleetState?.decisions_needed || []).map((d) => ({
        source: d.from,
        subject: 'Decision needed',
        summary: d.description,
        ts: asIsoOrNow(d.requested_at),
      })),
      ...inboxApprovals,
    ]
      .sort((a, b) => new Date(b.ts).getTime() - new Date(a.ts).getTime())
      .slice(0, 25)

    const research = bulletins
      .filter((b) => ['radar', 'herald', 'susan'].includes((b.from || '').toLowerCase()))
      .map((b) => ({
        source: b.from || 'fleet',
        category: b.category || 'update',
        summary: b.summary || b.subject || 'Research update',
        detail: (b.detail || '').slice(0, 260),
        ts: asIsoOrNow(b.ts || b.timestamp),
      }))
      .sort((a, b) => new Date(b.ts).getTime() - new Date(a.ts).getTime())
      .slice(0, 20)

    const goals = roadmapMd
      .split('\n')
      .filter((line) => line.includes('|') && (line.toLowerCase().includes('launch') || line.toLowerCase().includes('goal')))
      .slice(0, 15)

    const kanbanLines = kanbanMd
      .split('\n')
      .filter((line) => line.trim().startsWith('|') && !line.includes('---'))
      .slice(0, 20)

    const todayBulletins = bulletins
      .map((b) => ({
        ts: asIsoOrNow(b.ts || b.timestamp),
        type: 'bulletin',
        source: b.from || 'fleet',
        summary: b.summary || b.subject || 'Fleet bulletin',
      }))
      .filter((e) => isToday(e.ts))

    trackEvents = [...trackEvents, ...todayBulletins]
      .sort((a, b) => new Date(b.ts).getTime() - new Date(a.ts).getTime())
      .slice(0, 40)

    return NextResponse.json({
      timestamp: new Date().toISOString(),
      fleet: fleetState,
      system: systemHealth,
      services: { app: appHealth, growthEngine: growthHealth },
      controlCentre: {
        approvals,
        research,
        kanban: {
          lines: kanbanLines,
          source: '/home/ccuser/shared/KANBAN.md',
        },
        goals: {
          lines: goals,
          source: '/home/ccuser/shared/ROADMAP.md',
        },
        currentFocus: currentMd.split('\n').slice(0, 40),
        decisions: decisions.slice(-20),
        track: {
          dateUtc: new Date().toISOString().slice(0, 10),
          events: trackEvents,
        },
      },
    })
  } catch {
    return NextResponse.json({ error: 'Failed to gather fleet data' }, { status: 500 })
  }
}
