import { readFileSync, readdirSync } from 'node:fs'
import { resolve, dirname, relative } from 'node:path'
import { fileURLToPath } from 'node:url'
import { describe, it, expect } from 'vitest'

const __dirname = dirname(fileURLToPath(import.meta.url))
const projectRoot = resolve(__dirname, '../..')
const serverDir = resolve(projectRoot, 'server')

/** Collects all .js file paths under dir (recursive). */
function listJsFiles(dir, base = dir) {
  const entries = readdirSync(dir, { withFileTypes: true })
  const files = []
  for (const e of entries) {
    const full = resolve(dir, e.name)
    if (e.isDirectory()) {
      files.push(...listJsFiles(full, base))
    }
    else if (e.isFile() && e.name.endsWith('.js')) {
      files.push(relative(base, full))
    }
  }
  return files
}

/** Extracts relative import/require paths from file content (no node_modules). */
function getRelativeImports(content) {
  const paths = []
  const fromRegex = /from\s+['"]([^'"]+)['"]/g
  const requireRegex = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g
  const extractMatches = (regex, text) => {
    const matches = []
    const execRegex = (r) => {
      const match = r.exec(text)
      if (match) {
        matches.push(match[1])
        return execRegex(r)
      }
      return matches
    }
    return execRegex(regex)
  }
  for (const re of [fromRegex, requireRegex]) {
    const matches = extractMatches(re, content)
    matches.forEach((p) => {
      if (p.startsWith('.')) paths.push(p)
    })
  }
  return paths
}

describe('server imports', () => {
  it('only import from within server/ (no shared/ or other outside paths)', () => {
    const violations = []
    const files = listJsFiles(serverDir).map(f => resolve(serverDir, f))

    for (const filePath of files) {
      const content = readFileSync(filePath, 'utf-8')
      const fileDir = dirname(filePath)
      for (const importPath of getRelativeImports(content)) {
        const resolved = resolve(fileDir, importPath)
        const relToServer = relative(serverDir, resolved)
        if (relToServer.startsWith('..') || relToServer.startsWith('/')) {
          violations.push({
            file: relative(projectRoot, filePath),
            import: importPath,
            resolved: relative(projectRoot, resolved),
          })
        }
      }
    }

    expect(
      violations,
      violations.length
        ? `Server files must not import from outside server/. Violations:\n${violations
          .map(v => `  ${v.file} → ${v.import} (resolves to ${v.resolved})`)
          .join('\n')}`
        : undefined,
    ).toHaveLength(0)
  })
})
