package com.correx.core.artifacts.kind

/**
 * Infers a [KindContractTable] key from a written file's workspace-relative path (Gate 2, Option B:
 * runtime-manifest-driven — the plan declares a generic `file_written` slot, so the semantic kind is
 * recovered from the path at gate time).
 *
 * Pure and deterministic over the path string — no filesystem access — so it is replay-safe. An
 * unrecognized path returns `null`; the caller then falls back to the universal floor, so an
 * unknown file is still checked for existence + non-emptiness + parse, never skipped.
 *
 * This is heuristic by nature. Option A (planner declares `{path, kind}` targets) supersedes it for
 * stages that opt in; until then this recovers the common cases for the stacks correx exercises.
 */
object KindInference {

    fun kindFor(path: String): String? {
        val name = path.substringAfterLast('/')
        val lower = name.lowercase()
        return when {
            lower == "package.json" -> "package_json"
            lower.startsWith("tsconfig") && lower.endsWith(".json") -> "tsconfig"
            lower.startsWith("vite.config.") -> "vite_config"
            lower.endsWith(".html") -> "html_entry"
            lower.endsWith(".css") || lower.endsWith(".scss") -> "css_entry"
            lower.endsWith(".gradle.kts") || lower == "build.gradle" -> "gradle_module"
            name.endsWith(".tsx") || name.endsWith(".ts") -> tsKind(path, name)
            name.endsWith(".kt") -> kotlinKind(name)
            lower.endsWith(".json") -> "json_config"
            lower.endsWith(".md") -> "docs"
            else -> null
        }
    }

    private fun tsKind(path: String, name: String): String {
        val stem = name.substringBeforeLast('.')
        return when {
            // App entry points (src/main.tsx, index.tsx) mount the tree via createRoot/render and
            // legitimately export nothing — requiring a default component (react_view) makes the
            // stage unwinnable for a correct file. Lenient contract: exists · non-empty · imports.
            name.endsWith(".tsx") && (stem == "main" || stem == "index") -> "react_entry"
            stem.startsWith("use") && stem.length > 3 && stem[3].isUpperCase() -> "react_hook"
            "/types/" in path || stem == "types" -> "ts_types"
            "/views/" in path || stem.endsWith("View") -> "react_view"
            "router" in stem.lowercase() || "routes" in stem.lowercase() -> "router_config"
            name.endsWith(".tsx") && stem.isNotEmpty() && stem[0].isUpperCase() -> "react_component"
            name.endsWith(".tsx") -> "react_view"
            else -> "ts_module"
        }
    }

    private fun kotlinKind(name: String): String {
        val stem = name.removeSuffix(".kt")
        return when {
            stem.endsWith("Event") || stem.endsWith("Events") -> "kotlin_event"
            stem.endsWith("Reducer") -> "kotlin_reducer"
            stem.endsWith("Projector") || stem.endsWith("Projection") -> "kotlin_projector"
            stem.endsWith("Repository") -> "kotlin_repository"
            stem.endsWith("Test") || stem.endsWith("Tests") -> "kotlin_test"
            stem.endsWith("Service") || stem.endsWith("Facade") -> "kotlin_service"
            else -> "kotlin_service"
        }
    }
}
