/**
 * Symbolic Evaluation Test File - Kotlin
 *
 * This file contains multiple source→sink flows for testing symbolic evaluation.
 * Each section demonstrates dangerous (unsafe) and safe patterns.
 *
 * Patterns covered:
 * - SQL injection (string templates vs parameterized)
 * - Command injection (ProcessBuilder)
 * - Ktor/Spring request handling
 * - Null safety operators
 * - Extension functions
 * - Data classes and destructuring
 */

package com.example.symbolic

import java.io.File
import java.sql.Connection
import java.sql.PreparedStatement
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

// =============================================================================
// SQL INJECTION PATTERNS
// =============================================================================

class UserRepository(private val connection: Connection) {

    // UNSAFE: String template with user input
    fun getUserUnsafeTemplate(userId: String): User? {
        val query = "SELECT * FROM users WHERE id = '$userId'"
        val stmt = connection.createStatement()
        val rs = stmt.executeQuery(query)  // Sink: danger
        return if (rs.next()) User(rs.getString("id"), rs.getString("username")) else null
    }

    // UNSAFE: String concatenation
    fun getUserUnsafeConcat(username: String): User? {
        val query = "SELECT * FROM users WHERE username = '" + username + "'"
        val stmt = connection.createStatement()
        val rs = stmt.executeQuery(query)  // Sink: danger
        return if (rs.next()) User(rs.getString("id"), rs.getString("username")) else null
    }

    // SAFE: PreparedStatement with parameters
    fun getUserSafePrepared(userId: String): User? {
        val query = "SELECT * FROM users WHERE id = ?"
        val stmt = connection.prepareStatement(query)
        stmt.setString(1, userId)  // Safe: parameterized
        val rs = stmt.executeQuery()
        return if (rs.next()) User(rs.getString("id"), rs.getString("username")) else null
    }

    // SAFE: Constant query
    fun getAllUsersSafe(): List<User> {
        val query = "SELECT * FROM users"
        val stmt = connection.createStatement()
        val rs = stmt.executeQuery(query)  // Safe: constant
        val users = mutableListOf<User>()
        while (rs.next()) {
            users.add(User(rs.getString("id"), rs.getString("username")))
        }
        return users
    }
}

// =============================================================================
// COMMAND INJECTION PATTERNS
// =============================================================================

class CommandService {

    // UNSAFE: ProcessBuilder with shell command
    fun executeUnsafeShell(filename: String): String {
        val command = "cat $filename"
        val process = ProcessBuilder("sh", "-c", command).start()  // Sink: danger
        return process.inputStream.bufferedReader().readText()
    }

    // UNSAFE: Runtime.exec with concatenation
    fun executeUnsafeRuntime(path: String): String {
        val command = "ls $path"
        val process = Runtime.getRuntime().exec(command)  // Sink: danger
        return process.inputStream.bufferedReader().readText()
    }

    // SAFE: ProcessBuilder with list (no shell)
    fun executeSafeList(filename: String): String {
        val process = ProcessBuilder("cat", filename).start()  // Safer
        return process.inputStream.bufferedReader().readText()
    }

    // SAFE: Constant command
    fun listDirectorySafe(): String {
        val process = ProcessBuilder("ls", "-la").start()  // Safe
        return process.inputStream.bufferedReader().readText()
    }
}

// =============================================================================
// FILE OPERATIONS PATTERNS
// =============================================================================

class FileService(private val basePath: String) {

    // UNSAFE: String template path
    fun readFileUnsafeTemplate(filename: String): String {
        val path = "$basePath/$filename"
        return File(path).readText()  // Sink: path traversal
    }

    // UNSAFE: Plus operator concatenation
    fun readFileUnsafePlus(filename: String): String {
        val path = basePath + "/" + filename
        return File(path).readText()  // Sink: danger
    }

    // SAFE: Validated path
    fun readFileSafe(filename: String): String {
        require(!filename.contains("..") && !filename.startsWith("/")) {
            "Invalid filename"
        }
        val path = "$basePath/$filename"
        return File(path).readText()  // Safe after validation
    }
}

// =============================================================================
// NULL SAFETY PATTERNS
// =============================================================================

class NullSafetyService {

    // UNSAFE: Elvis operator with danger
    fun processWithElvis(input: String?): String {
        val value = input ?: "default"  // Danger if input is not null
        return value
    }

    // UNSAFE: Safe call propagates danger
    fun processWithSafeCall(input: String?): String? {
        return input?.uppercase()  // Danger propagates through safe call
    }

    // UNSAFE: Let scope function
    fun processWithLet(input: String?): String {
        return input?.let { value ->
            value.uppercase()  // Danger inside let block
        } ?: "default"
    }

    // SAFE: All branches are constants
    fun processConstant(flag: Boolean): String {
        return if (flag) "option_a" else "option_b"
    }
}

// =============================================================================
// EXTENSION FUNCTION PATTERNS
// =============================================================================

// UNSAFE: Extension on dangerous receiver
fun String.processUnsafe(): String {
    return this.uppercase()  // 'this' may be dangerous
}

// UNSAFE: Extension with dangerous parameter
fun String.appendUnsafe(suffix: String): String {
    return this + suffix  // Both may be dangerous
}

// SAFE: Extension with constant
fun String.appendSafe(): String {
    return this + "_suffix"  // Suffix is constant
}

// =============================================================================
// DATA CLASS AND DESTRUCTURING
// =============================================================================

data class User(val id: String, val username: String)

data class RequestData(val filename: String, val userId: String)

class DestructuringService {

    // UNSAFE: Destructuring extracts dangerous values
    fun processRequestUnsafe(data: RequestData): String {
        val (filename, userId) = data  // Destructuring
        return filename  // Danger from destructured value
    }

    // UNSAFE: Component access
    fun getFilenameUnsafe(data: RequestData): String {
        return data.component1()  // Same as data.filename
    }
}

// =============================================================================
// KTOR ROUTING (Sources)
// =============================================================================

fun Application.configureRouting() {
    routing {
        // UNSAFE: Query parameter to SQL
        get("/user/unsafe") {
            val userId = call.request.queryParameters["id"] ?: ""  // Source
            val repo = UserRepository(getConnection())
            val user = repo.getUserUnsafeTemplate(userId)  // Danger
            call.respond(user ?: "Not found")
        }

        // SAFE: Parameterized query
        get("/user/safe") {
            val userId = call.request.queryParameters["id"] ?: ""  // Source
            val repo = UserRepository(getConnection())
            val user = repo.getUserSafePrepared(userId)  // Safe
            call.respond(user ?: "Not found")
        }

        // UNSAFE: Path parameter to command
        get("/exec/unsafe/{filename}") {
            val filename = call.parameters["filename"] ?: ""  // Source
            val service = CommandService()
            val result = service.executeUnsafeShell(filename)  // Danger
            call.respondText(result)
        }

        // UNSAFE: Body to file read
        post("/file/unsafe") {
            val request = call.receive<RequestData>()  // Source
            val service = FileService("/var/data")
            val content = service.readFileUnsafeTemplate(request.filename)  // Danger
            call.respondText(content)
        }
    }
}

// =============================================================================
// VARIABLE PROPAGATION PATTERNS
// =============================================================================

class DataProcessor {

    // UNSAFE: Val assignment propagates danger
    fun processUnsafe(input: String): String {
        val processed = input  // Assignment propagates
        val transformed = processed.uppercase()  // Method on dangerous
        return transformed
    }

    // UNSAFE: Also/apply scope functions
    fun processWithAlso(input: String): String {
        return input.also { println(it) }  // Returns same dangerous value
    }

    // SAFE: Reassignment with var
    fun processSafe(input: String): String {
        var processed = input
        processed = "constant_value"  // Reassignment breaks danger
        return processed
    }
}

// =============================================================================
// CONTROL FLOW PATTERNS
// =============================================================================

class ControlFlowService {

    // UNSAFE: When expression with danger
    fun whenUnsafe(userInput: String): String {
        return when {
            userInput.isNotEmpty() -> userInput  // Danger
            else -> "default"
        }
    }

    // UNSAFE: If expression
    fun ifExpressionUnsafe(userInput: String): String {
        return if (userInput.length > 0) userInput else "default"
    }

    // SAFE: When with constants
    fun whenSafe(code: Int): String {
        return when (code) {
            1 -> "option_a"
            2 -> "option_b"
            else -> "default"
        }
    }
}

// Helper function
fun getConnection(): Connection = TODO()
