using Microsoft.Extensions.Logging;

namespace ColaFlow.Modules.Mcp.Infrastructure.Validation;

/// <summary>
/// Validates that all database queries include TenantId filtering
/// This is a defense-in-depth security measure to ensure multi-tenant isolation
/// </summary>
public interface ITenantContextValidator
{
    /// <summary>
    /// Validate that a query includes TenantId filter
    /// </summary>
    /// <param name="queryString">The SQL query string</param>
    /// <returns>True if query includes TenantId filter, false otherwise</returns>
    bool ValidateQueryIncludesTenantFilter(string queryString);

    /// <summary>
    /// Validate that the current request has a valid tenant context
    /// </summary>
    /// <returns>True if tenant context is set, false otherwise</returns>
    bool ValidateTenantContextIsSet();

    /// <summary>
    /// Get validation statistics
    /// </summary>
    TenantValidationStats GetValidationStats();
}

/// <summary>
/// Tenant validation statistics
/// </summary>
public class TenantValidationStats
{
    public long TotalQueriesValidated { get; set; }
    public long QueriesWithTenantFilter { get; set; }
    public long QueriesWithoutTenantFilter { get; set; }
    public List<string> ViolatingQueries { get; set; } = new();
}

/// <summary>
/// Implementation of tenant context validator
/// Uses EF Core Query Tags and SQL inspection to verify tenant filtering
/// </summary>
public class TenantContextValidator : ITenantContextValidator
{
    private readonly ILogger<TenantContextValidator> _logger;
    private readonly TenantValidationStats _stats;

    public TenantContextValidator(ILogger<TenantContextValidator> logger)
    {
        _logger = logger;
        _stats = new TenantValidationStats();
    }

    /// <summary>
    /// Validate that a query includes TenantId filter
    /// Checks for WHERE clause containing TenantId
    /// </summary>
    public bool ValidateQueryIncludesTenantFilter(string queryString)
    {
        if (string.IsNullOrWhiteSpace(queryString))
        {
            _logger.LogWarning("Empty query string provided for validation");
            return false;
        }

        _stats.TotalQueriesValidated++;

        // Check if query contains TenantId filter
        var hasTenantFilter = queryString.Contains("TenantId", StringComparison.OrdinalIgnoreCase) ||
                             queryString.Contains("Tenant_Id", StringComparison.OrdinalIgnoreCase) ||
                             queryString.Contains("[TenantId]", StringComparison.OrdinalIgnoreCase);

        if (hasTenantFilter)
        {
            _stats.QueriesWithTenantFilter++;
            _logger.LogDebug("Query validation PASSED - TenantId filter present");
            return true;
        }
        else
        {
            _stats.QueriesWithoutTenantFilter++;
            _stats.ViolatingQueries.Add(queryString);
            _logger.LogWarning("SECURITY WARNING: Query validation FAILED - No TenantId filter detected: {Query}",
                TruncateQuery(queryString));
            return false;
        }
    }

    /// <summary>
    /// Validate that the current request has a valid tenant context
    /// This should be called at the start of every MCP operation
    /// </summary>
    public bool ValidateTenantContextIsSet()
    {
        // Note: This would typically check HttpContext.Items["McpTenantId"]
        // For now, we'll log a placeholder
        _logger.LogDebug("Tenant context validation requested");
        return true; // Placeholder - implement with actual context check
    }

    /// <summary>
    /// Get validation statistics
    /// Used for security reporting
    /// </summary>
    public TenantValidationStats GetValidationStats()
    {
        return _stats;
    }

    /// <summary>
    /// Truncate query string for logging (avoid excessive log sizes)
    /// </summary>
    private string TruncateQuery(string query)
    {
        const int maxLength = 200;
        if (query.Length <= maxLength)
            return query;

        return query.Substring(0, maxLength) + "...";
    }
}

/// <summary>
/// Exception thrown when tenant context validation fails
/// </summary>
public class TenantContextValidationException : Exception
{
    public TenantContextValidationException(string message) : base(message)
    {
    }

    public TenantContextValidationException(string message, Exception innerException)
        : base(message, innerException)
    {
    }
}
