// src/SIGCM.API/Controllers/PaymentsController.cs
using MercadoPago.Client.Payment;
using Microsoft.AspNetCore.Mvc;
using SIGCM.Domain.Entities;
using SIGCM.Domain.Interfaces;
using SIGCM.Infrastructure.Services;
using SIGCM.Infrastructure.Repositories;

namespace SIGCM.API.Controllers;

[ApiController]
[Route("api/[controller]")]
public class PaymentsController : ControllerBase
{
    private readonly MercadoPagoService _mpService;
    private readonly IListingRepository _listingRepo;
    private readonly AuditRepository _auditRepo;

    public PaymentsController(MercadoPagoService mpService, IListingRepository listingRepo, AuditRepository auditRepo)
    {
        _mpService = mpService;
        _listingRepo = listingRepo;
        _auditRepo = auditRepo;
    }

    /*
    IMPLEMENTACIÓN REAL (COMENTADA PARA FASE FINAL)
    [HttpPost("create-preference/{listingId}")]
    public async Task<IActionResult> CreatePreference(int listingId, [FromBody] decimal amount)
    {
        var listing = await _listingRepo.GetByIdAsync(listingId);
        if (listing == null) return NotFound("Aviso no encontrado");

        var preference = await _mpService.CreatePreferenceAsync(listing, amount);
        
        return Ok(new { 
            id = preference.Id, 
            initPoint = preference.InitPoint, // Para redirección
            sandboxInitPoint = preference.SandboxInitPoint // Para testing
        });
    }
    */
    [HttpPost("create-preference/{listingId}")]
    public async Task<IActionResult> CreatePreference(int listingId, [FromBody] decimal amount)
    {
        var listing = await _listingRepo.GetByIdAsync(listingId);
        if (listing == null) return NotFound("Aviso no encontrado");

        // Llamamos al servicio (que ahora devuelve el objeto simulado)
        var preference = await _mpService.CreatePreferenceAsync(listing, amount);

        return Ok(preference);
    }

    public class SimulationRequest { public decimal Amount { get; set; } }

    [HttpPost("confirm-simulation/{listingId}")]
    public async Task<IActionResult> ConfirmSimulation(int listingId, [FromBody] SimulationRequest request)
    {
        var listing = await _listingRepo.GetByIdAsync(listingId);
        if (listing == null) return NotFound();

        // 1. El aviso queda en 'Pending' (Moderación), no 'Published'
        await _listingRepo.UpdateStatusAsync(listingId, "Pending");

        // 2. Registrar el pago
        var paymentRecord = new Payment
        {
            ListingId = listingId,
            Amount = request.Amount,
            PaymentMethod = "MercadoPago (Simulado)",
            PaymentDate = DateTime.UtcNow,
            ExternalReference = listingId.ToString(),
            ExternalId = "SIM-" + Guid.NewGuid().ToString().Substring(0, 8),
            Status = "Approved"
        };

        await _listingRepo.AddPaymentAsync(paymentRecord);

        // Audit Log
        var userIdStr = User.FindFirst("Id")?.Value;
        if (int.TryParse(userIdStr, out int userId))
        {
            await _auditRepo.AddLogAsync(new AuditLog
            {
                UserId = userId,
                Action = "CONFIRM_PAYMENT",
                EntityId = listingId,
                EntityType = "Payment",
                Details = $"Pago confirmado (Simulado). Monto: ${request.Amount}",
                CreatedAt = DateTime.UtcNow
            });
        }

        return Ok(new { message = "Pago registrado. Aviso enviado a moderación." });
    }

    [HttpPost("webhook")]
    public async Task<IActionResult> Webhook([FromQuery] string id, [FromQuery] string topic)
    {
        if (topic == "payment")
        {
            var client = new PaymentClient();
            var mpPayment = await client.GetAsync(long.Parse(id));

            if (mpPayment.Status == "approved")
            {
                var listingId = int.Parse(mpPayment.ExternalReference);
                var listing = await _listingRepo.GetByIdAsync(listingId);

                if (listing != null && listing.Status != "Published")
                {
                    // 1. Cambiar estado a PUBLISHED
                    await _listingRepo.UpdateStatusAsync(listingId, "Pending");

                    // 2. Registrar el pago en la tabla Payments
                    var paymentRecord = new Payment
                    {
                        ListingId = listingId,
                        Amount = mpPayment.TransactionAmount ?? 0,
                        PaymentMethod = "MercadoPago",
                        PaymentDate = DateTime.UtcNow,
                        ExternalReference = mpPayment.ExternalReference,
                        ExternalId = mpPayment.Id.ToString(),
                        Status = "Approved"
                    };

                    await _listingRepo.AddPaymentAsync(paymentRecord);
                }
            }
        }

        return Ok();
    }
}
