using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MktZaloService.API.Application.Commands.Webhook;
using MktZaloService.Infrastructure.Zalo.Models;
using System.Text.Json;

namespace MktZaloService.API.Controllers;

/// <summary>
/// EN: Controller for handling Zalo webhook events.
/// VI: Controller để xử lý các sự kiện webhook từ Zalo.
/// </summary>
[ApiController]
[Route("api/v1/webhooks")]
[AllowAnonymous] // Zalo webhooks don't use JWT
public class WebhooksController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<WebhooksController> _logger;

    public WebhooksController(IMediator mediator, ILogger<WebhooksController> logger)
    {
        _mediator = mediator;
        _logger = logger;
    }

    /// <summary>
    /// EN: Webhook verification endpoint (GET) - Zalo sends challenge token.
    /// VI: Endpoint xác thực webhook (GET) - Zalo gửi token thử thách.
    /// </summary>
    [HttpGet("zalo")]
    public IActionResult VerifyWebhook([FromQuery(Name = "hub.challenge")] string? challenge)
    {
        _logger.LogInformation(
            "EN: Webhook verification request received. VI: Đã nhận yêu cầu xác thực webhook");

        if (!string.IsNullOrEmpty(challenge))
        {
            return Ok(challenge);
        }

        return Ok("Webhook endpoint ready");
    }

    /// <summary>
    /// EN: Webhook event handler endpoint (POST).
    /// VI: Endpoint xử lý sự kiện webhook (POST).
    /// </summary>
    [HttpPost("zalo")]
    public async Task<IActionResult> HandleWebhook(
        [FromHeader(Name = "X-ZaloOA-Signature")] string? signature,
        CancellationToken ct)
    {
        // EN: Read raw body for signature verification
        // VI: Đọc body thô để xác thực chữ ký
        using var reader = new StreamReader(Request.Body);
        var rawBody = await reader.ReadToEndAsync(ct);

        if (string.IsNullOrEmpty(rawBody))
        {
            return BadRequest(new { error = "Empty request body" });
        }

        // EN: Parse webhook event
        // VI: Phân tích sự kiện webhook
        ZaloWebhookEvent? webhookEvent;
        try
        {
            webhookEvent = JsonSerializer.Deserialize<ZaloWebhookEvent>(rawBody, new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
            });
        }
        catch (JsonException ex)
        {
            _logger.LogWarning(ex, "EN: Invalid webhook JSON. VI: JSON webhook không hợp lệ");
            return BadRequest(new { error = "Invalid JSON" });
        }

        if (webhookEvent == null)
        {
            return BadRequest(new { error = "Could not parse webhook event" });
        }

        // EN: Process webhook (must respond quickly < 5s)
        // VI: Xử lý webhook (phải phản hồi nhanh < 5s)
        var command = new ProcessWebhookCommand(
            webhookEvent,
            rawBody,
            signature ?? string.Empty);

        var result = await _mediator.Send(command, ct);

        // EN: Always return 200 to acknowledge receipt (per Zalo spec)
        // VI: Luôn trả về 200 để xác nhận đã nhận (theo spec Zalo)
        if (result.Success)
        {
            return Ok(new { success = true, message_id = result.MessageId });
        }

        _logger.LogWarning(
            "EN: Webhook processing failed: {Error}. VI: Xử lý webhook thất bại: {Error}",
            result.Error);

        // EN: Still return 200 to avoid Zalo retries for business logic errors
        // VI: Vẫn trả về 200 để tránh Zalo retry cho lỗi business logic
        return Ok(new { success = false, error = result.Error });
    }
}
