/**
 * useFlowLayout — Auto-Layout und Edge-Formeln für das V2 FlowCanvas
 *
 * Portiert von agents.js (design_handoff_nexus_v2).
 * Enthält alle Positionslogik, Edge-Erzeugung und den Typ AgentNodeData.
 */

export interface Point {
  x: number
  y: number
}

export interface AgentNodeData {
  id: string
  name: string
  role: string
  roleBadge?: string
  model: string
  avatar: string
  status: 'work' | 'think' | 'idle' | 'block'
  statusLabel: string
  task: string | null
  goal: string | null
  progress: number
  elapsed: string
  next: string
  tokens: string
  cost: string
  think: string | null
  handoff?: string
  from?: string
  links?: string[]
  md?: string
}

export interface EdgeData {
  a: string
  b: string
  kind: 'orch' | 'flow'
}

/**
 * Auto-Layout Algorithmus
 * Iris immer top-center (x:50%, y:14%).
 * Andere Agenten in Reihen (maxPerRow variiert nach Gesamtzahl).
 */
export function autoLayout(agents: AgentNodeData[]): Record<string, Point> {
  const positions: Record<string, Point> = { iris: { x: 50, y: 14 } }
  const others = agents.filter(a => a.id !== 'iris')
  const n = others.length
  if (n === 0) return positions

  const maxPerRow = n <= 2 ? 2 : n <= 6 ? 3 : n <= 9 ? 3 : 4
  const numRows = Math.ceil(n / maxPerRow)
  const yStart = n <= 3 ? 58 : 30
  const yEnd = 86
  const yVals = numRows === 1
    ? [yStart]
    : Array.from({ length: numRows }, (_, i) => yStart + (yEnd - yStart) * i / (numRows - 1))

  let idx = 0
  yVals.forEach(y => {
    const rowN = Math.min(maxPerRow, n - idx)
    const xSpan = Math.min(72, 24 * (rowN - 1) + 18)
    const xOff = 50 - xSpan / 2
    const xStep = rowN > 1 ? xSpan / (rowN - 1) : 0
    for (let ci = 0; ci < rowN; ci++, idx++) {
      positions[others[idx].id] = { x: xOff + ci * xStep, y }
    }
  })

  return positions
}

/**
 * Erzeugt die Kantenliste basierend auf Agenten-Daten
 * (gleiche Logik wie buildEdges in agents.js).
 */
export function buildEdges(agents: AgentNodeData[]): EdgeData[] {
  const edges: EdgeData[] = []

  // Orchestrierung: Iris → jeder Agent
  agents.filter(a => a.id !== 'iris').forEach(a => {
    edges.push({ a: 'iris', b: a.id, kind: 'orch' })
  })

  // Spezifische Flows (wenn Agent existiert)
  const hasId = (id: string) => agents.some(a => a.id === id)
  if (hasId('dev') && hasId('rev')) edges.push({ a: 'dev', b: 'rev', kind: 'flow' })
  if (hasId('arch') && hasId('exec')) edges.push({ a: 'arch', b: 'exec', kind: 'flow' })
  if (hasId('res')) edges.push({ a: 'res', b: 'iris', kind: 'flow' })
  if (hasId('qa') && hasId('rev')) edges.push({ a: 'qa', b: 'rev', kind: 'flow' })
  if (hasId('security')) edges.push({ a: 'security', b: 'iris', kind: 'flow' })
  if (hasId('pm')) edges.push({ a: 'pm', b: 'iris', kind: 'flow' })
  if (hasId('devops') && hasId('exec')) edges.push({ a: 'exec', b: 'devops', kind: 'flow' })

  return edges
}

/**
 * Bézier-Kurve zwischen zwei Punkten
 * Verwendet die README.p1 und p2)) Formel:
 * M p1 Q Kontrollpunkt p2
 * mx,my = Mittelpunkt; off = min(50, hypot*0.14)
 * len = hypot(-dy, dx) (Normale)
 * cp = (mx + (-dy/len)*off, my + (dx/len)*off)
 */
export function curve(p1: Point, p2: Point): string {
  const mx = (p1.x + p2.x) / 2
  const my = (p1.y + p2.y) / 2
  const dx = p2.x - p1.x
  const dy = p2.y - p1.y
  const off = Math.min(50, Math.hypot(dx, dy) * 0.14)
  const len = Math.hypot(-dy, dx) || 1
  const cx = mx + (-dy / len) * off
  const cy = my + (dx / len) * off
  return `M${p1.x},${p1.y} Q${cx},${cy} ${p2.x},${p2.y}`
}

/**
 * Extra agents that can be added to the FlowBoard dynamically
 */
export const extraAgentPool: AgentNodeData[] = [
  {
    id: 'qa',
    name: 'QA Automator',
    role: 'Test Automation',
    roleBadge: 'badge-cyan',
    avatar: 'QA',
    status: 'idle',
    statusLabel: 'Bereit',
    task: 'End-to-End Tests schreiben',
    goal: '100% Coverage für auth/',
    progress: 0,
    elapsed: '—',
    next: 'Testplan erstellen',
    model: 'Deepseek V4 Flash',
    tokens: '0',
    cost: '0.00',
    think: null,
  },
  {
    id: 'devops',
    name: 'DevOps',
    role: 'CI/CD Pipeline',
    roleBadge: 'badge-amber',
    avatar: 'DO',
    status: 'idle',
    statusLabel: 'Bereit',
    task: 'GitHub Actions Workflow',
    goal: 'Automatisches Deploy auf merge',
    progress: 0,
    elapsed: '—',
    next: 'Pipeline konfigurieren',
    model: 'Deepseek V4 Pro',
    tokens: '0',
    cost: '0.00',
    think: null,
  },
  {
    id: 'security',
    name: 'Security Scanner',
    role: 'Security Analysis',
    roleBadge: 'badge-rose',
    avatar: 'SC',
    status: 'think',
    statusLabel: 'Scannt',
    task: 'Dependency-Audit durchführen',
    goal: 'CVEs in api/ aufdecken',
    progress: 18,
    elapsed: '00:01:44',
    next: 'Report an Iris',
    model: 'Deepseek V4 Pro',
    tokens: '9k',
    cost: '0.18',
    think: 'Analysiere package-lock.json auf bekannte Vulnerabilities…',
  },
  {
    id: 'pm',
    name: 'Project Manager',
    role: 'Coordination',
    roleBadge: 'badge-purple',
    avatar: 'PM',
    status: 'think',
    statusLabel: 'Plant',
    task: 'Sprint-Retrospektive vorbereiten',
    goal: 'Blockers identifizieren',
    progress: 35,
    elapsed: '00:05:10',
    next: 'Meeting-Summary an Team',
    model: 'Deepseek V4 Flash',
    tokens: '14k',
    cost: '0.24',
    think: 'Analysiere Velocity-Daten der letzten 3 Sprints…',
  },
]
