/**
 * Symbolic Evaluation Test File - C#
 *
 * This file contains multiple source→sink flows for testing symbolic evaluation.
 * Each section demonstrates dangerous (unsafe) and safe patterns.
 *
 * Patterns covered:
 * - SQL injection (string concat vs SqlCommand parameters)
 * - Command injection (Process.Start)
 * - Path traversal (File operations)
 * - ASP.NET Core request handling
 * - Entity Framework patterns
 * - LINQ expressions
 */

using System;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace SymbolicEvaluation
{
    // =========================================================================
    // SQL INJECTION PATTERNS
    // =========================================================================

    public class UserRepository
    {
        private readonly SqlConnection _connection;

        public UserRepository(SqlConnection connection)
        {
            _connection = connection;
        }

        // UNSAFE: String concatenation with user input
        public User GetUserUnsafeConcat(string userId)
        {
            string query = "SELECT * FROM Users WHERE Id = '" + userId + "'";
            SqlCommand cmd = new SqlCommand(query, _connection);
            var reader = cmd.ExecuteReader();  // Sink: danger
            return MapUser(reader);
        }

        // UNSAFE: String interpolation with user input
        public User GetUserUnsafeInterpolation(string username)
        {
            string query = $"SELECT * FROM Users WHERE Username = '{username}'";
            SqlCommand cmd = new SqlCommand(query, _connection);
            var reader = cmd.ExecuteReader();  // Sink: danger
            return MapUser(reader);
        }

        // UNSAFE: String.Format with user input
        public User GetUserUnsafeFormat(string email)
        {
            string query = String.Format("SELECT * FROM Users WHERE Email = '{0}'", email);
            SqlCommand cmd = new SqlCommand(query, _connection);
            var reader = cmd.ExecuteReader();  // Sink: danger
            return MapUser(reader);
        }

        // SAFE: SqlCommand with parameters
        public User GetUserSafeParameterized(string userId)
        {
            string query = "SELECT * FROM Users WHERE Id = @userId";
            SqlCommand cmd = new SqlCommand(query, _connection);
            cmd.Parameters.AddWithValue("@userId", userId);  // Safe
            var reader = cmd.ExecuteReader();
            return MapUser(reader);
        }

        // SAFE: Constant query
        public List<User> GetAllUsersSafe()
        {
            string query = "SELECT * FROM Users";
            SqlCommand cmd = new SqlCommand(query, _connection);
            var reader = cmd.ExecuteReader();  // Safe: constant
            return MapUsers(reader);
        }

        private User MapUser(SqlDataReader reader) => null;
        private List<User> MapUsers(SqlDataReader reader) => new List<User>();
    }

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

    public class CommandService
    {
        // UNSAFE: Process.Start with concatenated arguments
        public string ExecuteUnsafeConcat(string filename)
        {
            var startInfo = new ProcessStartInfo
            {
                FileName = "cmd.exe",
                Arguments = "/c type " + filename,  // Danger
                RedirectStandardOutput = true
            };
            var process = Process.Start(startInfo);  // Sink: danger
            return process.StandardOutput.ReadToEnd();
        }

        // UNSAFE: Interpolated command
        public string ExecuteUnsafeInterpolation(string path)
        {
            var startInfo = new ProcessStartInfo
            {
                FileName = "cmd.exe",
                Arguments = $"/c dir {path}",  // Danger
                RedirectStandardOutput = true
            };
            var process = Process.Start(startInfo);  // Sink: danger
            return process.StandardOutput.ReadToEnd();
        }

        // SAFE: Direct file execution (no shell)
        public string ExecuteSafeNoShell(string filename)
        {
            var startInfo = new ProcessStartInfo
            {
                FileName = "cat",
                Arguments = filename,  // Safer: no shell interpretation
                RedirectStandardOutput = true,
                UseShellExecute = false
            };
            var process = Process.Start(startInfo);
            return process.StandardOutput.ReadToEnd();
        }

        // SAFE: Constant command
        public string ListDirectorySafe()
        {
            var startInfo = new ProcessStartInfo
            {
                FileName = "cmd.exe",
                Arguments = "/c dir",  // Safe: constant
                RedirectStandardOutput = true
            };
            var process = Process.Start(startInfo);
            return process.StandardOutput.ReadToEnd();
        }
    }

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

    public class FileService
    {
        private readonly string _basePath;

        public FileService(string basePath)
        {
            _basePath = basePath;
        }

        // UNSAFE: Path.Combine with user input (still traversable)
        public string ReadFileUnsafeCombine(string filename)
        {
            string path = Path.Combine(_basePath, filename);
            return File.ReadAllText(path);  // Sink: path traversal
        }

        // UNSAFE: String concatenation path
        public string ReadFileUnsafeConcat(string filename)
        {
            string path = _basePath + "\\" + filename;
            return File.ReadAllText(path);  // Sink: danger
        }

        // SAFE: Validated path
        public string ReadFileSafe(string filename)
        {
            if (filename.Contains("..") || Path.IsPathRooted(filename))
            {
                throw new SecurityException("Invalid filename");
            }
            string path = Path.Combine(_basePath, filename);
            return File.ReadAllText(path);  // Safe after validation
        }
    }

    // =========================================================================
    // ASP.NET CORE CONTROLLER (Sources)
    // =========================================================================

    [ApiController]
    [Route("api/[controller]")]
    public class UserController : ControllerBase
    {
        private readonly UserRepository _userRepository;
        private readonly CommandService _commandService;
        private readonly FileService _fileService;

        // UNSAFE: Query parameter to SQL
        [HttpGet("unsafe")]
        public IActionResult GetUserUnsafe([FromQuery] string id)
        {
            var user = _userRepository.GetUserUnsafeConcat(id);  // Danger
            return Ok(user);
        }

        // SAFE: Parameterized query
        [HttpGet("safe")]
        public IActionResult GetUserSafe([FromQuery] string id)
        {
            var user = _userRepository.GetUserSafeParameterized(id);  // Safe
            return Ok(user);
        }

        // UNSAFE: Route parameter to command
        [HttpGet("exec/unsafe/{filename}")]
        public IActionResult ExecUnsafe(string filename)
        {
            var result = _commandService.ExecuteUnsafeConcat(filename);  // Danger
            return Ok(result);
        }

        // UNSAFE: Body to file read
        [HttpPost("file/unsafe")]
        public IActionResult ReadFileUnsafe([FromBody] FileRequest request)
        {
            var content = _fileService.ReadFileUnsafeConcat(request.Filename);
            return Ok(content);
        }
    }

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

    public class DataProcessor
    {
        // UNSAFE: Assignment propagates danger
        public string ProcessUnsafe(string input)
        {
            string processed = input;  // Assignment propagates
            string transformed = processed.ToUpper();  // Method on dangerous
            return transformed;
        }

        // UNSAFE: Multiple assignments
        public string ChainAssignmentUnsafe(string value)
        {
            string a = value;
            string b = a;
            string c = b;
            return c;  // Danger propagates
        }

        // SAFE: Reassignment to constant
        public string ProcessInputSafe(string input)
        {
            string processed = input;
            processed = "constant_value";  // Breaks danger
            return processed;
        }
    }

    // =========================================================================
    // LINQ PATTERNS
    // =========================================================================

    public class LinqService
    {
        private readonly List<User> _users;

        // UNSAFE: LINQ with dangerous predicate
        public User FindUserUnsafe(string searchTerm)
        {
            return _users.FirstOrDefault(u => u.Username.Contains(searchTerm));
        }

        // UNSAFE: Select projects dangerous data
        public IEnumerable<string> ProjectUnsafe(string prefix)
        {
            return _users.Select(u => prefix + u.Username);  // Danger in projection
        }

        // SAFE: Constant predicate
        public List<User> GetActiveUsersSafe()
        {
            return _users.Where(u => u.IsActive).ToList();  // Safe
        }
    }

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

    public class ControlFlowService
    {
        // UNSAFE: Danger through conditional
        public string ConditionalUnsafe(string userInput)
        {
            string result;
            if (!string.IsNullOrEmpty(userInput))
            {
                result = userInput;  // Danger in true branch
            }
            else
            {
                result = "default";
            }
            return result;
        }

        // UNSAFE: Null-coalescing with danger
        public string NullCoalescingUnsafe(string userInput)
        {
            return userInput ?? "default";  // Danger if not null
        }

        // SAFE: Both branches are constants
        public string ConditionalSafe(bool flag)
        {
            return flag ? "option_a" : "option_b";  // Both safe
        }
    }

    // =========================================================================
    // SUPPORTING CLASSES
    // =========================================================================

    public class User
    {
        public string Id { get; set; }
        public string Username { get; set; }
        public bool IsActive { get; set; }
    }

    public class FileRequest
    {
        public string Filename { get; set; }
    }
}
