using BTCPayServer.Client;
using BTCPayServer.Client.Models;
using LittleShop.Enums;
using Newtonsoft.Json.Linq;

namespace LittleShop.Services;

public interface IBTCPayServerService
{
    Task<string> CreateInvoiceAsync(decimal amount, CryptoCurrency currency, string orderId, string? description = null);
    Task<InvoiceData?> GetInvoiceAsync(string invoiceId);
    Task<bool> ValidateWebhookAsync(string payload, string signature);
}

public class BTCPayServerService : IBTCPayServerService
{
    private readonly BTCPayServerClient _client;
    private readonly IConfiguration _configuration;
    private readonly string _storeId;
    private readonly string _webhookSecret;

    public BTCPayServerService(IConfiguration configuration)
    {
        _configuration = configuration;
        
        var baseUrl = _configuration["BTCPayServer:BaseUrl"] ?? throw new ArgumentException("BTCPayServer:BaseUrl not configured");
        var apiKey = _configuration["BTCPayServer:ApiKey"] ?? throw new ArgumentException("BTCPayServer:ApiKey not configured");
        _storeId = _configuration["BTCPayServer:StoreId"] ?? throw new ArgumentException("BTCPayServer:StoreId not configured");
        _webhookSecret = _configuration["BTCPayServer:WebhookSecret"] ?? throw new ArgumentException("BTCPayServer:WebhookSecret not configured");

        // Create HttpClient with certificate bypass for internal networks
        var httpClient = new HttpClient(new HttpClientHandler()
        {
            ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
        });
        
        _client = new BTCPayServerClient(new Uri(baseUrl), apiKey, httpClient);
    }

    public async Task<string> CreateInvoiceAsync(decimal amount, CryptoCurrency currency, string orderId, string? description = null)
    {
        var currencyCode = GetCurrencyCode(currency);
        
        var metadata = new JObject
        {
            ["orderId"] = orderId,
            ["currency"] = currencyCode
        };

        if (!string.IsNullOrEmpty(description))
        {
            metadata["itemDesc"] = description;
        }

        var request = new CreateInvoiceRequest
        {
            Amount = amount,
            Currency = currencyCode,
            Metadata = metadata,
            Checkout = new CreateInvoiceRequest.CheckoutOptions
            {
                Expiration = TimeSpan.FromHours(24)
            }
        };

        try
        {
            var invoice = await _client.CreateInvoice(_storeId, request);
            return invoice.Id;
        }
        catch (Exception ex)
        {
            // Log the specific error for debugging
            Console.WriteLine($"BTCPay Server error for {currencyCode}: {ex.Message}");
            
            // Try to continue with real API call for all cryptocurrencies with configured wallets
            if (currency == CryptoCurrency.BTC || currency == CryptoCurrency.LTC || currency == CryptoCurrency.DASH || currency == CryptoCurrency.XMR)
            {
                throw; // Let the calling service handle errors for supported currencies
            }
            
            // For XMR and ETH, we have nodes but BTCPay Server might not be configured yet
            // Log the error and fall back to placeholder for now
            Console.WriteLine($"Falling back to placeholder for {currencyCode} - BTCPay Server integration pending");
            return $"invoice_{Guid.NewGuid()}";
        }
    }

    public async Task<InvoiceData?> GetInvoiceAsync(string invoiceId)
    {
        try
        {
            return await _client.GetInvoice(_storeId, invoiceId);
        }
        catch
        {
            return null;
        }
    }

    public Task<bool> ValidateWebhookAsync(string payload, string signature)
    {
        try
        {
            // BTCPay Server uses HMAC-SHA256 with format "sha256=<hex>"
            if (!signature.StartsWith("sha256="))
            {
                return Task.FromResult(false);
            }

            var expectedHash = signature.Substring(7); // Remove "sha256=" prefix
            var secretBytes = System.Text.Encoding.UTF8.GetBytes(_webhookSecret);
            var payloadBytes = System.Text.Encoding.UTF8.GetBytes(payload);

            using var hmac = new System.Security.Cryptography.HMACSHA256(secretBytes);
            var computedHash = hmac.ComputeHash(payloadBytes);
            var computedHashHex = Convert.ToHexString(computedHash).ToLowerInvariant();

            return Task.FromResult(expectedHash.Equals(computedHashHex, StringComparison.OrdinalIgnoreCase));
        }
        catch
        {
            return Task.FromResult(false);
        }
    }

    private static string GetCurrencyCode(CryptoCurrency currency)
    {
        return currency switch
        {
            CryptoCurrency.BTC => "BTC",
            CryptoCurrency.XMR => "XMR", 
            CryptoCurrency.USDT => "USDT",
            CryptoCurrency.LTC => "LTC",
            CryptoCurrency.ETH => "ETH",
            CryptoCurrency.ZEC => "ZEC",
            CryptoCurrency.DASH => "DASH",
            CryptoCurrency.DOGE => "DOGE",
            _ => "BTC"
        };
    }

    private static string GetPaymentMethod(CryptoCurrency currency)
    {
        return currency switch
        {
            CryptoCurrency.BTC => "BTC",
            CryptoCurrency.XMR => "XMR",
            CryptoCurrency.USDT => "USDT_ETH", // USDT on Ethereum
            CryptoCurrency.LTC => "LTC",
            CryptoCurrency.ETH => "ETH",
            CryptoCurrency.ZEC => "ZEC",
            CryptoCurrency.DASH => "DASH", 
            CryptoCurrency.DOGE => "DOGE",
            _ => "BTC"
        };
    }
}