using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using LittleShop.DTOs;
using LittleShop.Services;
using LittleShop.Enums;

namespace LittleShop.Controllers;

[ApiController]
[Route("api/[controller]")]
[Authorize(AuthenticationSchemes = "Bearer")]
public class OrdersController : ControllerBase
{
    private readonly IOrderService _orderService;
    private readonly ICryptoPaymentService _cryptoPaymentService;

    public OrdersController(IOrderService orderService, ICryptoPaymentService cryptoPaymentService)
    {
        _orderService = orderService;
        _cryptoPaymentService = cryptoPaymentService;
    }

    // Admin endpoints
    [HttpGet]
    [Authorize(Roles = "Admin")]
    public async Task<ActionResult<IEnumerable<OrderDto>>> GetAllOrders()
    {
        var orders = await _orderService.GetAllOrdersAsync();
        return Ok(orders);
    }

    [HttpGet("{id}")]
    [Authorize(Roles = "Admin")]
    public async Task<ActionResult<OrderDto>> GetOrder(Guid id)
    {
        var order = await _orderService.GetOrderByIdAsync(id);
        if (order == null)
        {
            return NotFound();
        }

        return Ok(order);
    }

    [HttpPut("{id}/status")]
    [Authorize(Roles = "Admin")]
    public async Task<ActionResult> UpdateOrderStatus(Guid id, [FromBody] UpdateOrderStatusDto updateOrderStatusDto)
    {
        var success = await _orderService.UpdateOrderStatusAsync(id, updateOrderStatusDto);
        if (!success)
        {
            return NotFound();
        }

        return NoContent();
    }

    // Public endpoints for client identity
    [HttpGet("by-identity/{identityReference}")]
    [AllowAnonymous]
    public async Task<ActionResult<IEnumerable<OrderDto>>> GetOrdersByIdentity(string identityReference)
    {
        var orders = await _orderService.GetOrdersByIdentityAsync(identityReference);
        return Ok(orders);
    }

    [HttpGet("by-customer/{customerId}")]
    [AllowAnonymous]
    public async Task<ActionResult<IEnumerable<OrderDto>>> GetOrdersByCustomerId(Guid customerId)
    {
        var orders = await _orderService.GetOrdersByCustomerIdAsync(customerId);
        return Ok(orders);
    }

    [HttpGet("by-customer/{customerId}/{id}")]
    [AllowAnonymous]
    public async Task<ActionResult<OrderDto>> GetOrderByCustomerId(Guid customerId, Guid id)
    {
        var order = await _orderService.GetOrderByIdAsync(id);
        if (order == null || order.CustomerId != customerId)
        {
            return NotFound();
        }

        return Ok(order);
    }

    [HttpGet("by-identity/{identityReference}/{id}")]
    [AllowAnonymous]
    public async Task<ActionResult<OrderDto>> GetOrderByIdentity(string identityReference, Guid id)
    {
        var order = await _orderService.GetOrderByIdAsync(id);
        if (order == null || order.IdentityReference != identityReference)
        {
            return NotFound();
        }

        return Ok(order);
    }

    [HttpPost]
    [AllowAnonymous]
    public async Task<ActionResult<OrderDto>> CreateOrder([FromBody] CreateOrderDto createOrderDto)
    {
        try
        {
            var order = await _orderService.CreateOrderAsync(createOrderDto);
            return CreatedAtAction(nameof(GetOrderByIdentity), 
                new { identityReference = order.IdentityReference, id = order.Id }, order);
        }
        catch (ArgumentException ex)
        {
            return BadRequest(ex.Message);
        }
    }

    [HttpPost("{id}/payments")]
    [AllowAnonymous]
    public async Task<ActionResult<CryptoPaymentDto>> CreatePayment(Guid id, [FromBody] CreatePaymentDto createPaymentDto)
    {
        var order = await _orderService.GetOrderByIdAsync(id);
        if (order == null)
        {
            return NotFound("Order not found");
        }

        try
        {
            var payment = await _cryptoPaymentService.CreatePaymentAsync(id, createPaymentDto.Currency);
            return Ok(payment);
        }
        catch (ArgumentException ex)
        {
            return BadRequest(ex.Message);
        }
    }

    [HttpGet("{id}/payments")]
    public async Task<ActionResult<IEnumerable<CryptoPaymentDto>>> GetOrderPayments(Guid id)
    {
        var payments = await _cryptoPaymentService.GetPaymentsByOrderAsync(id);
        return Ok(payments);
    }

    [HttpGet("payments/{paymentId}/status")]
    public async Task<ActionResult<PaymentStatusDto>> GetPaymentStatus(Guid paymentId)
    {
        try
        {
            var status = await _cryptoPaymentService.GetPaymentStatusAsync(paymentId);
            return Ok(status);
        }
        catch (ArgumentException)
        {
            return NotFound();
        }
    }

    [HttpPost("{id}/cancel")]
    public async Task<ActionResult> CancelOrder(Guid id, [FromBody] CancelOrderDto cancelOrderDto)
    {
        var success = await _orderService.CancelOrderAsync(id, cancelOrderDto.IdentityReference);
        if (!success)
        {
            return BadRequest("Cannot cancel order - order not found or already processed");
        }

        return NoContent();
    }

    // Webhook endpoint for BTCPay Server
    [HttpPost("payments/webhook")]
    public async Task<ActionResult> PaymentWebhook([FromBody] PaymentWebhookDto webhookDto)
    {
        var success = await _cryptoPaymentService.ProcessPaymentWebhookAsync(
            webhookDto.InvoiceId, 
            webhookDto.Status, 
            webhookDto.Amount, 
            webhookDto.TransactionHash);

        if (!success)
        {
            return BadRequest("Invalid webhook data");
        }

        return Ok();
    }
}

public class CreatePaymentDto
{
    public CryptoCurrency Currency { get; set; }
}

public class CancelOrderDto
{
    public string IdentityReference { get; set; } = string.Empty;
}

public class PaymentWebhookDto
{
    public string InvoiceId { get; set; } = string.Empty;
    public PaymentStatus Status { get; set; }
    public decimal Amount { get; set; }
    public string? TransactionHash { get; set; }
}