using Microsoft.AspNetCore.Mvc;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using LittleShop.DTOs;
using LittleShop.Services;
using LittleShop.Enums;

namespace LittleShop.Controllers;

[ApiController]
[Route("api/btcpay")]
public class BTCPayWebhookController : ControllerBase
{
    private readonly ICryptoPaymentService _cryptoPaymentService;
    private readonly IBTCPayServerService _btcPayService;
    private readonly IConfiguration _configuration;
    private readonly ILogger<BTCPayWebhookController> _logger;

    public BTCPayWebhookController(
        ICryptoPaymentService cryptoPaymentService,
        IBTCPayServerService btcPayService,
        IConfiguration configuration,
        ILogger<BTCPayWebhookController> logger)
    {
        _cryptoPaymentService = cryptoPaymentService;
        _btcPayService = btcPayService;
        _configuration = configuration;
        _logger = logger;
    }

    [HttpPost("webhook")]
    public async Task<IActionResult> ProcessWebhook()
    {
        try
        {
            // Read the raw request body
            using var reader = new StreamReader(Request.Body);
            var requestBody = await reader.ReadToEndAsync();

            // Get webhook signature from headers
            var signature = Request.Headers["BTCPAY-SIG"].FirstOrDefault();
            
            if (string.IsNullOrEmpty(signature))
            {
                _logger.LogWarning("Webhook received without signature");
                return BadRequest("Missing webhook signature");
            }

            // Validate webhook signature
            var webhookSecret = _configuration["BTCPayServer:WebhookSecret"];
            if (string.IsNullOrEmpty(webhookSecret))
            {
                _logger.LogError("BTCPay webhook secret not configured");
                return StatusCode(500, "Webhook validation not configured");
            }

            if (!ValidateWebhookSignature(requestBody, signature, webhookSecret))
            {
                _logger.LogWarning("Invalid webhook signature");
                return BadRequest("Invalid webhook signature");
            }

            // Parse webhook data
            var webhookData = JsonSerializer.Deserialize<BTCPayWebhookDto>(requestBody, new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            });

            if (webhookData == null)
            {
                _logger.LogWarning("Unable to parse webhook data");
                return BadRequest("Invalid webhook data");
            }

            _logger.LogInformation("Processing BTCPay webhook: Type={Type}, InvoiceId={InvoiceId}, StoreId={StoreId}", 
                webhookData.Type, webhookData.InvoiceId, webhookData.StoreId);

            // Process the webhook based on event type
            var success = await ProcessWebhookEvent(webhookData);

            if (!success)
            {
                return BadRequest("Failed to process webhook");
            }

            return Ok();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error processing BTCPay webhook");
            return StatusCode(500, "Internal server error");
        }
    }

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

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

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

            return expectedHash.Equals(computedHashHex, StringComparison.OrdinalIgnoreCase);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error validating webhook signature");
            return false;
        }
    }

    private async Task<bool> ProcessWebhookEvent(BTCPayWebhookDto webhookData)
    {
        try
        {
            // Map BTCPay webhook event types to our payment status
            var paymentStatus = MapWebhookEventToPaymentStatus(webhookData.Type);
            
            if (!paymentStatus.HasValue)
            {
                _logger.LogInformation("Ignoring webhook event type: {Type}", webhookData.Type);
                return true; // Not an error, just not a status we care about
            }

            // Extract payment details
            var amount = webhookData.Payment?.PaymentMethodPaid ?? 0;
            var transactionHash = webhookData.Payment?.TransactionData?.TransactionHash;

            // Process the payment update
            var success = await _cryptoPaymentService.ProcessPaymentWebhookAsync(
                webhookData.InvoiceId,
                paymentStatus.Value,
                amount,
                transactionHash);

            if (success)
            {
                _logger.LogInformation("Successfully processed webhook for invoice {InvoiceId} with status {Status}", 
                    webhookData.InvoiceId, paymentStatus.Value);
            }
            else
            {
                _logger.LogWarning("Failed to process webhook for invoice {InvoiceId}", webhookData.InvoiceId);
            }

            return success;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error processing webhook event for invoice {InvoiceId}", webhookData.InvoiceId);
            return false;
        }
    }

    private static PaymentStatus? MapWebhookEventToPaymentStatus(string eventType)
    {
        return eventType switch
        {
            "InvoiceCreated" => PaymentStatus.Pending,
            "InvoiceReceivedPayment" => PaymentStatus.Processing,
            "InvoicePaymentSettled" => PaymentStatus.Completed,
            "InvoiceProcessing" => PaymentStatus.Processing,
            "InvoiceExpired" => PaymentStatus.Expired,
            "InvoiceSettled" => PaymentStatus.Completed,
            "InvoiceInvalid" => PaymentStatus.Failed,
            _ => null // Unknown event type
        };
    }
}