PythonIntegration.kt

package com.depanalyzer.parser.python

import com.depanalyzer.core.graph.DependencyNode
import com.depanalyzer.parser.DependencySection
import com.depanalyzer.parser.Ecosystem
import com.depanalyzer.parser.ParsedDependency
import java.io.File

object PythonIntegration {
    private val pyprojectParser = PyprojectPoetryParser()
    private val poetryLockParser = PoetryLockParser()
    private val requirementsParser = RequirementsParser()

    fun analyzePoetryProject(projectDir: File): Pair<List<ParsedDependency>, List<DependencyNode>> {
        val pyprojectFile = File(projectDir, "pyproject.toml")
        val directDependencies = if (pyprojectFile.exists()) {
            pyprojectParser.parse(pyprojectFile)
        } else {
            emptyList()
        }

        val lockFile = File(projectDir, "poetry.lock")
        val roots = poetryLockParser.parse(lockFile, directDependencies)

        val dependencies = if (roots.isNotEmpty()) {
            flatten(roots)
        } else {
            directDependencies
        }

        val rootNodes = if (roots.isNotEmpty()) {
            roots
        } else {
            directDependencies.map { dep ->
                DependencyNode(
                    id = "pypi:${dep.artifactId}:${dep.version}",
                    groupId = dep.groupId,
                    artifactId = dep.artifactId,
                    version = dep.version ?: "unknown",
                    scope = dep.scope,
                    ecosystem = Ecosystem.PYPI
                )
            }
        }

        return Pair(dependencies, rootNodes)
    }

    fun analyzeRequirementsProject(projectDir: File): Pair<List<ParsedDependency>, List<DependencyNode>> {
        val requirementsFile = File(projectDir, "requirements.txt")
        val dependencies = requirementsParser.parse(requirementsFile)

        val rootNodes = dependencies.map { dep ->
            DependencyNode(
                id = "pypi:${dep.artifactId}:${dep.version}",
                groupId = dep.groupId,
                artifactId = dep.artifactId,
                version = dep.version ?: "unknown",
                scope = dep.scope,
                ecosystem = Ecosystem.PYPI
            )
        }

        return Pair(dependencies, rootNodes)
    }

    private fun flatten(nodes: List<DependencyNode>): List<ParsedDependency> {
        val result = mutableListOf<ParsedDependency>()

        fun visit(node: DependencyNode) {
            result += ParsedDependency(
                groupId = node.groupId,
                artifactId = node.artifactId,
                version = node.version,
                scope = node.scope ?: "main",
                section = DependencySection.DEPENDENCIES,
                ecosystem = Ecosystem.PYPI
            )
            node.children.forEach(::visit)
        }

        nodes.forEach(::visit)
        return result
    }
}