MavenIntegration.kt

package com.depanalyzer.parser.maven

import com.depanalyzer.cli.ProgressTracker
import com.depanalyzer.core.graph.DependencyNode
import com.depanalyzer.parser.PomDependencyParser
import java.io.File
import kotlin.time.Duration.Companion.seconds

object MavenIntegration {
    private val staticParser = PomDependencyParser()

    fun analyzeMavenProject(
        projectDir: File,
        enableMaven: Boolean = true,
        verbose: Boolean = false,
        timeoutSeconds: Long = 1800L,
        showCommandOutput: Boolean = false
    ): List<DependencyNode> {
        val pomFile = File(projectDir, "pom.xml")

        if (!enableMaven) {
            ProgressTracker.logWarning("Análisis dinámico deshabilitado. Usando análisis estático (menos preciso).")
            if (verbose) {
                System.err.println("[MavenIntegration] Offline mode enabled. Using static analysis (less precise).")
            }
            return fallbackToStaticParsing(pomFile, verbose)
        }

        ProgressTracker.logSearching("Buscando Maven...")
        if (MavenDetector.findMavenCommand(projectDir, verbose) == null) {
            ProgressTracker.logWarning("Maven no encontrado. Usando análisis estático (menos preciso).")
            if (verbose) {
                System.err.println("[MavenIntegration] No maven command found (checked: project wrapper and global mvn), falling back to static parsing")
            }
            return fallbackToStaticParsing(pomFile, verbose)
        }

        ProgressTracker.logProcessing("Analizando dependencias Maven...")
        val treeOutput = MavenCommandExecutor.execute(
            projectDir,
            timeout = timeoutSeconds.seconds,
            verbose = verbose,
            isDefaultTimeout = (timeoutSeconds == 1800L),
            onOutputLine = if (showCommandOutput) {
                { line -> ProgressTracker.logStep("   [maven] $line") }
            } else {
                null
            }
        )
        if (treeOutput == null) {
            ProgressTracker.logWarning("Análisis dinámico falló. Usando análisis estático (menos preciso).")
            if (verbose) {
                System.err.println("[MavenIntegration] Maven execution failed, timed out, or produced no output")
            }
            return fallbackToStaticParsing(pomFile, verbose)
        }

        if (verbose) {
            System.err.println("[MavenIntegration] Using dynamic Maven analysis")
        }

        val parsedNodes = MavenDependencyTreeParser.parse(treeOutput, verbose = verbose)
        ProgressTracker.logSuccess("${parsedNodes.size} dependencias encontradas")
        return parsedNodes
    }

    private fun fallbackToStaticParsing(pomFile: File, verbose: Boolean = false): List<DependencyNode> {
        if (verbose) {
            System.err.println("[MavenIntegration] Falling back to static parsing")
        }
        return try {
            val parsedDeps = staticParser.parse(pomFile)

            if (verbose) {
                System.err.println("[MavenIntegration] Static parsing found ${parsedDeps.size} dependencies")
            }

            val nodes = parsedDeps.map { dep ->
                DependencyNode(
                    id = "${dep.groupId}:${dep.artifactId}",
                    groupId = dep.groupId,
                    artifactId = dep.artifactId,
                    version = dep.version ?: "unknown",
                    parent = null,
                    children = mutableListOf(),
                    scope = dep.scope,
                    isDependencyManagement = dep.section == com.depanalyzer.parser.DependencySection.DEPENDENCY_MANAGEMENT
                )
            }.distinctBy { "${it.groupId}:${it.artifactId}" }

            ProgressTracker.logSuccess("${nodes.size} dependencias encontradas (análisis estático)")
            nodes
        } catch (e: IllegalArgumentException) {
            if (verbose) {
                System.err.println("[MavenIntegration] Static parsing failed: ${e.message}")
            }
            emptyList()
        }
    }
}