using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using PgpCore;

namespace TeleBot.Services
{
    public interface IPrivacyService
    {
        string HashIdentifier(long telegramId);
        string GenerateAnonymousReference();
        Task<string?> EncryptWithPGP(string data, string publicKey);
        Task<HttpClient> CreateTorHttpClient();
        byte[] EncryptData(byte[] data, string key);
        byte[] DecryptData(byte[] encryptedData, string key);
        void SanitizeLogMessage(ref string message);
    }
    
    public class PrivacyService : IPrivacyService
    {
        private readonly IConfiguration _configuration;
        private readonly ILogger<PrivacyService> _logger;
        private readonly string _salt;
        
        public PrivacyService(IConfiguration configuration, ILogger<PrivacyService> logger)
        {
            _configuration = configuration;
            _logger = logger;
            _salt = configuration["Privacy:HashSalt"] ?? "TeleBot-Privacy-Salt-2024";
        }
        
        public string HashIdentifier(long telegramId)
        {
            using var sha256 = SHA256.Create();
            var bytes = Encoding.UTF8.GetBytes($"{telegramId}:{_salt}");
            var hash = sha256.ComputeHash(bytes);
            return Convert.ToBase64String(hash);
        }
        
        public string GenerateAnonymousReference()
        {
            // Generate a random reference that can't be linked back to user
            var bytes = new byte[16];
            using var rng = RandomNumberGenerator.Create();
            rng.GetBytes(bytes);
            
            var reference = Convert.ToBase64String(bytes)
                .Replace("+", "")
                .Replace("/", "")
                .Replace("=", "")
                .Substring(0, 12)
                .ToUpper();
            
            return $"ANON-{reference}";
        }
        
        public async Task<string?> EncryptWithPGP(string data, string publicKey)
        {
            try
            {
                // TODO: Implement PGP encryption when PgpCore API is stable
                _logger.LogWarning("PGP encryption not implemented - returning base64 encoded data as placeholder");
                await Task.CompletedTask;
                return Convert.ToBase64String(Encoding.UTF8.GetBytes($"PGP_PLACEHOLDER:{data}"));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to encrypt with PGP");
                return null;
            }
        }
        
        public Task<HttpClient> CreateTorHttpClient()
        {
            if (!_configuration.GetValue<bool>("Privacy:EnableTor"))
            {
                // Return regular HttpClient if Tor is disabled
                return Task.FromResult(new HttpClient());
            }
            
            try
            {
                // Use existing Tor SOCKS proxy if available
                var torPort = _configuration.GetValue<int>("Privacy:TorSocksPort", 9050);
                var proxy = new WebProxy($"socks5://localhost:{torPort}");
                var handler = new HttpClientHandler
                {
                    Proxy = proxy,
                    UseProxy = true
                };
                
                return Task.FromResult(new HttpClient(handler));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to create Tor HTTP client, falling back to regular client");
                return Task.FromResult(new HttpClient());
            }
        }
        
        public byte[] EncryptData(byte[] data, string key)
        {
            using var aes = Aes.Create();
            aes.Mode = CipherMode.CBC;
            
            // Derive key from string
            using var sha256 = SHA256.Create();
            aes.Key = sha256.ComputeHash(Encoding.UTF8.GetBytes(key));
            
            var nonce = new byte[12];
            using var rng = RandomNumberGenerator.Create();
            rng.GetBytes(nonce);
            aes.IV = nonce;
            
            using var encryptor = aes.CreateEncryptor();
            var encrypted = encryptor.TransformFinalBlock(data, 0, data.Length);
            
            // Combine nonce and encrypted data
            var result = new byte[nonce.Length + encrypted.Length];
            Buffer.BlockCopy(nonce, 0, result, 0, nonce.Length);
            Buffer.BlockCopy(encrypted, 0, result, nonce.Length, encrypted.Length);
            
            return result;
        }
        
        public byte[] DecryptData(byte[] encryptedData, string key)
        {
            using var aes = Aes.Create();
            aes.Mode = CipherMode.CBC;
            
            // Derive key from string
            using var sha256 = SHA256.Create();
            aes.Key = sha256.ComputeHash(Encoding.UTF8.GetBytes(key));
            
            // Extract nonce
            var nonce = new byte[12];
            Buffer.BlockCopy(encryptedData, 0, nonce, 0, nonce.Length);
            aes.IV = nonce;
            
            // Extract encrypted portion
            var encrypted = new byte[encryptedData.Length - nonce.Length];
            Buffer.BlockCopy(encryptedData, nonce.Length, encrypted, 0, encrypted.Length);
            
            using var decryptor = aes.CreateDecryptor();
            return decryptor.TransformFinalBlock(encrypted, 0, encrypted.Length);
        }
        
        public void SanitizeLogMessage(ref string message)
        {
            // Remove potential PII from log messages
            message = System.Text.RegularExpressions.Regex.Replace(
                message,
                @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b",
                "[EMAIL_REDACTED]"
            );
            
            message = System.Text.RegularExpressions.Regex.Replace(
                message,
                @"\b\d{3}[-.]?\d{3}[-.]?\d{4}\b",
                "[PHONE_REDACTED]"
            );
            
            message = System.Text.RegularExpressions.Regex.Replace(
                message,
                @"\b\d{16}\b",
                "[CARD_REDACTED]"
            );
            
            // Remove Telegram user IDs
            message = System.Text.RegularExpressions.Regex.Replace(
                message,
                @"telegram_id[:=]\d+",
                "telegram_id=[REDACTED]"
            );
        }
    }
}