const t = require('@babel/types')
const traverseMod = require('@babel/traverse')
const traverse = traverseMod.default || traverseMod

/**
 * BILDIT template library output needs `React` in scope for the classic JSX build path.
 * Ensures a default `React` binding from `'react'` when the file contains JSX and none exists.
 */
function ensureReactDefaultImportForJsx(ast) {
  let hasJsx = false
  traverse(ast, {
    enter(path) {
      if (path.isJSXElement() || path.isJSXFragment()) {
        hasJsx = true
        path.stop()
      }
    },
  })

  if (!hasJsx) {
    return
  }

  let firstValueReactImport = null
  for (const stmt of ast.program.body) {
    if (!t.isImportDeclaration(stmt)) {
      continue
    }
    if (stmt.source.value !== 'react') {
      continue
    }
    if (stmt.importKind === 'type') {
      continue
    }
    firstValueReactImport = stmt
    break
  }

  if (firstValueReactImport) {
    for (const s of firstValueReactImport.specifiers) {
      if (t.isImportDefaultSpecifier(s) && t.isIdentifier(s.local) && s.local.name === 'React') {
        return
      }
      if (t.isImportNamespaceSpecifier(s) && t.isIdentifier(s.local) && s.local.name === 'React') {
        return
      }
    }
    const hasNonReactNamespace = firstValueReactImport.specifiers.some(
      (s) => t.isImportNamespaceSpecifier(s) && t.isIdentifier(s.local) && s.local.name !== 'React',
    )
    if (hasNonReactNamespace) {
      insertReactDefaultImportStatement(ast, t)
      return
    }
    const defaultSpec = t.importDefaultSpecifier(t.identifier('React'))
    firstValueReactImport.specifiers.unshift(defaultSpec)
    return
  }

  insertReactDefaultImportStatement(ast, t)
}

function insertReactDefaultImportStatement(ast, t) {
  const newDecl = t.importDeclaration(
    [t.importDefaultSpecifier(t.identifier('React'))],
    t.stringLiteral('react'),
  )
  const body = ast.program.body
  let insertAt = 0
  if (
    body[0] &&
    t.isExpressionStatement(body[0]) &&
    t.isStringLiteral(body[0].expression) &&
    body[0].expression.value === 'use client'
  ) {
    insertAt = 1
  }
  const firstImportIdx = body.findIndex((n) => t.isImportDeclaration(n))
  if (firstImportIdx >= 0) {
    body.splice(firstImportIdx, 0, newDecl)
  } else {
    body.splice(insertAt, 0, newDecl)
  }
}

module.exports = {
  ensureReactDefaultImportForJsx,
}
