using Microsoft.Extensions.Logging;

namespace ColaFlow.Modules.Mcp.Infrastructure.Auditing;

/// <summary>
/// Security audit logger for MCP operations
/// Logs all security-relevant events including cross-tenant access attempts
/// </summary>
public interface IMcpSecurityAuditLogger
{
    /// <summary>
    /// Log successful MCP operation
    /// </summary>
    void LogSuccess(McpSecurityAuditEvent auditEvent);

    /// <summary>
    /// Log failed authentication attempt
    /// </summary>
    void LogAuthenticationFailure(McpSecurityAuditEvent auditEvent);

    /// <summary>
    /// Log cross-tenant access attempt (CRITICAL)
    /// </summary>
    void LogCrossTenantAccessAttempt(McpSecurityAuditEvent auditEvent);

    /// <summary>
    /// Log authorization failure
    /// </summary>
    void LogAuthorizationFailure(McpSecurityAuditEvent auditEvent);

    /// <summary>
    /// Get audit statistics
    /// </summary>
    McpAuditStatistics GetAuditStatistics();
}

/// <summary>
/// MCP security audit event
/// </summary>
public class McpSecurityAuditEvent
{
    public DateTime Timestamp { get; set; } = DateTime.UtcNow;
    public string EventType { get; set; } = string.Empty;
    public string? ApiKeyId { get; set; }
    public Guid? TenantId { get; set; }
    public Guid? UserId { get; set; }
    public string? Operation { get; set; }
    public string? ResourceType { get; set; }
    public Guid? ResourceId { get; set; }
    public Guid? TargetTenantId { get; set; } // For cross-tenant access attempts
    public string? IpAddress { get; set; }
    public bool Success { get; set; }
    public string? ErrorMessage { get; set; }
    public Dictionary<string, string>? AdditionalData { get; set; }
}

/// <summary>
/// MCP audit statistics
/// </summary>
public class McpAuditStatistics
{
    public long TotalOperations { get; set; }
    public long SuccessfulOperations { get; set; }
    public long FailedOperations { get; set; }
    public long AuthenticationFailures { get; set; }
    public long AuthorizationFailures { get; set; }
    public long CrossTenantAccessAttempts { get; set; }
    public DateTime LastCrossTenantAttempt { get; set; }
}

/// <summary>
/// Implementation of MCP security audit logger
/// </summary>
public class McpSecurityAuditLogger : IMcpSecurityAuditLogger
{
    private readonly ILogger<McpSecurityAuditLogger> _logger;
    private readonly McpAuditStatistics _statistics;
    private readonly object _statsLock = new();

    public McpSecurityAuditLogger(ILogger<McpSecurityAuditLogger> logger)
    {
        _logger = logger;
        _statistics = new McpAuditStatistics();
    }

    /// <summary>
    /// Log successful MCP operation
    /// </summary>
    public void LogSuccess(McpSecurityAuditEvent auditEvent)
    {
        lock (_statsLock)
        {
            _statistics.TotalOperations++;
            _statistics.SuccessfulOperations++;
        }

        _logger.LogInformation(
            "MCP Operation SUCCESS | Tenant: {TenantId} | User: {UserId} | Operation: {Operation} | Resource: {ResourceType}/{ResourceId}",
            auditEvent.TenantId,
            auditEvent.UserId,
            auditEvent.Operation,
            auditEvent.ResourceType,
            auditEvent.ResourceId);
    }

    /// <summary>
    /// Log failed authentication attempt
    /// </summary>
    public void LogAuthenticationFailure(McpSecurityAuditEvent auditEvent)
    {
        lock (_statsLock)
        {
            _statistics.TotalOperations++;
            _statistics.FailedOperations++;
            _statistics.AuthenticationFailures++;
        }

        _logger.LogWarning(
            "MCP Authentication FAILURE | IP: {IpAddress} | Reason: {ErrorMessage}",
            auditEvent.IpAddress,
            auditEvent.ErrorMessage);
    }

    /// <summary>
    /// Log cross-tenant access attempt (CRITICAL SECURITY EVENT)
    /// </summary>
    public void LogCrossTenantAccessAttempt(McpSecurityAuditEvent auditEvent)
    {
        lock (_statsLock)
        {
            _statistics.TotalOperations++;
            _statistics.FailedOperations++;
            _statistics.CrossTenantAccessAttempts++;
            _statistics.LastCrossTenantAttempt = DateTime.UtcNow;
        }

        _logger.LogCritical(
            "SECURITY ALERT: Cross-Tenant Access Attempt! | Attacker Tenant: {TenantId} | Target Tenant: {TargetTenantId} | " +
            "User: {UserId} | Resource: {ResourceType}/{ResourceId} | IP: {IpAddress}",
            auditEvent.TenantId,
            auditEvent.TargetTenantId,
            auditEvent.UserId,
            auditEvent.ResourceType,
            auditEvent.ResourceId,
            auditEvent.IpAddress);

        // TODO: Trigger security alert (email, Slack, PagerDuty, etc.)
        // TODO: Consider rate limiting or blocking tenant after multiple attempts
    }

    /// <summary>
    /// Log authorization failure
    /// </summary>
    public void LogAuthorizationFailure(McpSecurityAuditEvent auditEvent)
    {
        lock (_statsLock)
        {
            _statistics.TotalOperations++;
            _statistics.FailedOperations++;
            _statistics.AuthorizationFailures++;
        }

        _logger.LogWarning(
            "MCP Authorization FAILURE | Tenant: {TenantId} | User: {UserId} | Operation: {Operation} | " +
            "Resource: {ResourceType}/{ResourceId} | Reason: {ErrorMessage}",
            auditEvent.TenantId,
            auditEvent.UserId,
            auditEvent.Operation,
            auditEvent.ResourceType,
            auditEvent.ResourceId,
            auditEvent.ErrorMessage);
    }

    /// <summary>
    /// Get audit statistics
    /// </summary>
    public McpAuditStatistics GetAuditStatistics()
    {
        lock (_statsLock)
        {
            return new McpAuditStatistics
            {
                TotalOperations = _statistics.TotalOperations,
                SuccessfulOperations = _statistics.SuccessfulOperations,
                FailedOperations = _statistics.FailedOperations,
                AuthenticationFailures = _statistics.AuthenticationFailures,
                AuthorizationFailures = _statistics.AuthorizationFailures,
                CrossTenantAccessAttempts = _statistics.CrossTenantAccessAttempts,
                LastCrossTenantAttempt = _statistics.LastCrossTenantAttempt
            };
        }
    }
}

/// <summary>
/// Extension methods for audit logging
/// </summary>
public static class McpSecurityAuditLoggerExtensions
{
    /// <summary>
    /// Log MCP operation result with automatic success/failure handling
    /// </summary>
    public static void LogOperationResult(
        this IMcpSecurityAuditLogger auditLogger,
        McpSecurityAuditEvent auditEvent,
        bool success,
        string? errorMessage = null)
    {
        auditEvent.Success = success;
        auditEvent.ErrorMessage = errorMessage;

        if (success)
        {
            auditLogger.LogSuccess(auditEvent);
        }
        else
        {
            auditLogger.LogAuthorizationFailure(auditEvent);
        }
    }

    /// <summary>
    /// Create audit event from HTTP context
    /// </summary>
    public static McpSecurityAuditEvent CreateFromContext(
        Guid? tenantId,
        Guid? userId,
        string? apiKeyId,
        string operation,
        string? resourceType = null,
        Guid? resourceId = null,
        string? ipAddress = null)
    {
        return new McpSecurityAuditEvent
        {
            TenantId = tenantId,
            UserId = userId,
            ApiKeyId = apiKeyId,
            Operation = operation,
            ResourceType = resourceType,
            ResourceId = resourceId,
            IpAddress = ipAddress
        };
    }
}
