/**
 * Symbolic Evaluation Test File - Swift
 *
 * This file contains multiple source→sink flows for testing symbolic evaluation.
 * Each section demonstrates dangerous (unsafe) and safe patterns.
 *
 * Patterns covered:
 * - SQL injection (string interpolation vs parameterized)
 * - Command injection (Process)
 * - Path traversal (FileManager)
 * - URLSession request handling
 * - Optionals and nil coalescing
 * - Guard statements
 * - Closures and higher-order functions
 */

import Foundation
import SQLite3

// =============================================================================
// DATA MODELS
// =============================================================================

struct User: Codable {
    let id: String
    let username: String
    let email: String
}

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

class UserRepository {
    private var db: OpaquePointer?

    init(database: OpaquePointer?) {
        self.db = database
    }

    // UNSAFE: String interpolation with user input
    func getUserUnsafeInterpolation(userId: String) -> User? {
        let query = "SELECT * FROM users WHERE id = '\(userId)'"
        var stmt: OpaquePointer?
        sqlite3_prepare_v2(db, query, -1, &stmt, nil)  // Sink: danger
        return mapUser(stmt: stmt)
    }

    // UNSAFE: String concatenation
    func getUserUnsafeConcat(username: String) -> User? {
        let query = "SELECT * FROM users WHERE username = '" + username + "'"
        var stmt: OpaquePointer?
        sqlite3_prepare_v2(db, query, -1, &stmt, nil)  // Sink: danger
        return mapUser(stmt: stmt)
    }

    // UNSAFE: String format
    func getUserUnsafeFormat(email: String) -> User? {
        let query = String(format: "SELECT * FROM users WHERE email = '%@'", email)
        var stmt: OpaquePointer?
        sqlite3_prepare_v2(db, query, -1, &stmt, nil)  // Sink: danger
        return mapUser(stmt: stmt)
    }

    // SAFE: Parameterized query with binding
    func getUserSafeParameterized(userId: String) -> User? {
        let query = "SELECT * FROM users WHERE id = ?"
        var stmt: OpaquePointer?
        sqlite3_prepare_v2(db, query, -1, &stmt, nil)
        sqlite3_bind_text(stmt, 1, userId, -1, nil)  // Safe: parameterized
        return mapUser(stmt: stmt)
    }

    // SAFE: Constant query
    func getAllUsersSafe() -> [User] {
        let query = "SELECT * FROM users"
        var stmt: OpaquePointer?
        sqlite3_prepare_v2(db, query, -1, &stmt, nil)  // Safe: constant
        return mapUsers(stmt: stmt)
    }

    private func mapUser(stmt: OpaquePointer?) -> User? {
        guard sqlite3_step(stmt) == SQLITE_ROW else { return nil }
        let id = String(cString: sqlite3_column_text(stmt, 0))
        let username = String(cString: sqlite3_column_text(stmt, 1))
        let email = String(cString: sqlite3_column_text(stmt, 2))
        return User(id: id, username: username, email: email)
    }

    private func mapUsers(stmt: OpaquePointer?) -> [User] {
        var users: [User] = []
        while sqlite3_step(stmt) == SQLITE_ROW {
            let id = String(cString: sqlite3_column_text(stmt, 0))
            let username = String(cString: sqlite3_column_text(stmt, 1))
            let email = String(cString: sqlite3_column_text(stmt, 2))
            users.append(User(id: id, username: username, email: email))
        }
        return users
    }
}

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

class CommandService {
    // UNSAFE: Process with shell command
    func executeUnsafeShell(filename: String) -> String {
        let task = Process()
        task.executableURL = URL(fileURLWithPath: "/bin/sh")
        task.arguments = ["-c", "cat \(filename)"]  // Sink: danger

        let pipe = Pipe()
        task.standardOutput = pipe
        try? task.run()

        let data = pipe.fileHandleForReading.readDataToEndOfFile()
        return String(data: data, encoding: .utf8) ?? ""
    }

    // UNSAFE: String concatenation in arguments
    func executeUnsafeConcat(path: String) -> String {
        let task = Process()
        task.executableURL = URL(fileURLWithPath: "/bin/sh")
        task.arguments = ["-c", "ls " + path]  // Sink: danger

        let pipe = Pipe()
        task.standardOutput = pipe
        try? task.run()

        let data = pipe.fileHandleForReading.readDataToEndOfFile()
        return String(data: data, encoding: .utf8) ?? ""
    }

    // SAFE: Process with separate arguments
    func executeSafeArgs(filename: String) -> String {
        let task = Process()
        task.executableURL = URL(fileURLWithPath: "/bin/cat")
        task.arguments = [filename]  // Safer: no shell

        let pipe = Pipe()
        task.standardOutput = pipe
        try? task.run()

        let data = pipe.fileHandleForReading.readDataToEndOfFile()
        return String(data: data, encoding: .utf8) ?? ""
    }

    // SAFE: Constant command
    func listDirectorySafe() -> String {
        let task = Process()
        task.executableURL = URL(fileURLWithPath: "/bin/ls")
        task.arguments = ["-la"]  // Safe: constant

        let pipe = Pipe()
        task.standardOutput = pipe
        try? task.run()

        let data = pipe.fileHandleForReading.readDataToEndOfFile()
        return String(data: data, encoding: .utf8) ?? ""
    }
}

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

class FileService {
    private let basePath: String
    private let fileManager = FileManager.default

    init(basePath: String) {
        self.basePath = basePath
    }

    // UNSAFE: String interpolation path
    func readFileUnsafeInterpolation(filename: String) -> String? {
        let path = "\(basePath)/\(filename)"
        return try? String(contentsOfFile: path)  // Sink: path traversal
    }

    // UNSAFE: URL appending path component
    func readFileUnsafeURL(filename: String) -> String? {
        let url = URL(fileURLWithPath: basePath).appendingPathComponent(filename)
        return try? String(contentsOf: url)  // Sink: danger
    }

    // SAFE: Validated path
    func readFileSafe(filename: String) -> String? {
        guard !filename.contains(".."), !filename.hasPrefix("/") else {
            return nil  // Validation prevents traversal
        }
        let path = "\(basePath)/\(filename)"
        return try? String(contentsOfFile: path)  // Safe after validation
    }
}

// =============================================================================
// OPTIONAL AND NIL COALESCING PATTERNS
// =============================================================================

class OptionalService {
    // UNSAFE: Optional binding extracts danger
    func processOptionalUnsafe(input: String?) -> String {
        if let value = input {
            return value  // Danger from unwrapped optional
        }
        return "default"
    }

    // UNSAFE: Nil coalescing with danger
    func processNilCoalescingUnsafe(input: String?) -> String {
        return input ?? "default"  // Danger if not nil
    }

    // UNSAFE: Force unwrap
    func processForceUnwrapUnsafe(input: String?) -> String {
        return input!  // Danger (and crash risk)
    }

    // UNSAFE: Optional chaining propagates danger
    func processOptionalChainingUnsafe(input: String?) -> String? {
        return input?.uppercased()  // Danger propagates
    }

    // SAFE: Guard with constant fallback
    func processGuardSafe(input: String?) -> String {
        guard input != nil else {
            return "default"
        }
        return "constant_value"  // Returns constant, not input
    }
}

// =============================================================================
// GUARD STATEMENT PATTERNS
// =============================================================================

class GuardService {
    // UNSAFE: Guard doesn't sanitize, just checks presence
    func processGuardUnsafe(input: String?) -> String {
        guard let value = input, !value.isEmpty else {
            return "default"
        }
        return value  // Still dangerous after guard
    }

    // UNSAFE: Multiple guards still propagate danger
    func processMultipleGuardsUnsafe(input: String?) -> String {
        guard let step1 = input else { return "default" }
        guard step1.count < 100 else { return "too long" }
        return step1  // Danger propagates through guards
    }

    // SAFE: Guard with constant return
    func processGuardSafe(flag: Bool) -> String {
        guard flag else {
            return "option_b"
        }
        return "option_a"  // Both are constants
    }
}

// =============================================================================
// CLOSURE AND HIGHER-ORDER FUNCTION PATTERNS
// =============================================================================

class FunctionalService {
    // UNSAFE: Map propagates danger
    func processMapUnsafe(inputs: [String]) -> [String] {
        return inputs.map { $0.uppercased() }  // Danger propagates
    }

    // UNSAFE: Filter doesn't remove danger
    func processFilterUnsafe(inputs: [String]) -> [String] {
        return inputs.filter { !$0.isEmpty }  // Still dangerous
    }

    // UNSAFE: Reduce accumulates danger
    func processReduceUnsafe(inputs: [String]) -> String {
        return inputs.reduce("") { $0 + $1 }  // Danger accumulates
    }

    // UNSAFE: CompactMap with danger
    func processCompactMapUnsafe(inputs: [String?]) -> [String] {
        return inputs.compactMap { $0 }  // Danger from non-nil values
    }

    // SAFE: Map to constants
    func processMapSafe(inputs: [String]) -> [String] {
        return inputs.map { _ in "constant" }  // Transforms to constant
    }
}

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

class DataProcessor {
    // UNSAFE: Let assignment propagates danger
    func processUnsafe(input: String) -> String {
        let processed = input  // Assignment propagates
        let transformed = processed.uppercased()  // Method on dangerous
        return transformed
    }

    // UNSAFE: Multiple assignments
    func chainAssignmentUnsafe(value: String) -> String {
        let a = value
        let b = a
        let c = b
        return c  // Danger propagates
    }

    // SAFE: Var reassignment
    func processSafe(input: String) -> String {
        var processed = input
        processed = "constant_value"  // Reassignment breaks danger
        return processed
    }
}

// =============================================================================
// URL REQUEST HANDLERS (Sources)
// =============================================================================

class RequestHandler {
    private let userRepository: UserRepository
    private let commandService: CommandService
    private let fileService: FileService

    init(repo: UserRepository, cmd: CommandService, file: FileService) {
        self.userRepository = repo
        self.commandService = cmd
        self.fileService = file
    }

    // UNSAFE: URL query parameter to SQL
    func handleUserUnsafe(request: URLRequest) -> User? {
        guard let url = request.url,
              let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
              let userId = components.queryItems?.first(where: { $0.name == "id" })?.value else {
            return nil
        }
        return userRepository.getUserUnsafeInterpolation(userId: userId)  // Danger
    }

    // SAFE: Parameterized query
    func handleUserSafe(request: URLRequest) -> User? {
        guard let url = request.url,
              let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
              let userId = components.queryItems?.first(where: { $0.name == "id" })?.value else {
            return nil
        }
        return userRepository.getUserSafeParameterized(userId: userId)  // Safe
    }
}

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

class ControlFlowService {
    // UNSAFE: If-else with danger
    func conditionalUnsafe(userInput: String) -> String {
        if !userInput.isEmpty {
            return userInput  // Danger in true branch
        } else {
            return "default"
        }
    }

    // UNSAFE: Switch with danger
    func switchUnsafe(userInput: String, code: Int) -> String {
        switch code {
        case 1:
            return userInput  // Danger
        case 2:
            return "option_b"
        default:
            return "default"
        }
    }

    // SAFE: Both branches are constants
    func conditionalSafe(flag: Bool) -> String {
        return flag ? "option_a" : "option_b"  // Both safe
    }
}
