using Microsoft.AspNetCore.Mvc;
using Nop.Core;
using Nop.Core.Domain.Customers;
using Nop.Core.Domain.Orders;
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
using Nop.Plugin.Misc.FruitBankPlugin.Services;
using Nop.Services.Catalog;
using Nop.Services.Common;
using Nop.Services.Customers;
using Nop.Services.Directory;
using Nop.Services.Orders;
using Nop.Web.Framework;
using Nop.Web.Framework.Controllers;
using Nop.Web.Framework.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
{
    [Area(AreaNames.ADMIN)]
    [AuthorizeAdmin]
    public class InnVoiceOrderController : BasePluginController
    {
        private readonly IOrderService _orderService;
        private readonly IWorkContext _workContext;
        private readonly IStoreContext _storeContext;
        private readonly ICustomerService _customerService;
        private readonly ICountryService _countryService;
        private readonly IProductService _productService;
        private readonly InnVoiceOrderService _innVoiceOrderService;
        private readonly FruitBankAttributeService _fruitBankAttributeService;
        private readonly IGenericAttributeService _genericAttributeService;
        private readonly FruitBankDbContext _dbContext;

        public InnVoiceOrderController(
            IOrderService orderService,
            IWorkContext workContext,
            IStoreContext storeContext,
            ICustomerService customerService,
            ICountryService countryService,
            IProductService productService,
            InnVoiceOrderService innVoiceOrderService,
            FruitBankAttributeService fruitBankAttributeService,
            IGenericAttributeService genericAttributeService,
            FruitBankDbContext dbContext)
        {
            _orderService = orderService;
            _workContext = workContext;
            _storeContext = storeContext;
            _customerService = customerService;
            _countryService = countryService;
            _productService = productService;
            _innVoiceOrderService = innVoiceOrderService;
            _fruitBankAttributeService = fruitBankAttributeService;
            _genericAttributeService = genericAttributeService;
            _dbContext = dbContext;
        }

        /// <summary>
        /// Create an order in InnVoice from a NopCommerce order
        /// </summary>
        [HttpPost]
        [IgnoreAntiforgeryToken]
        public async Task<IActionResult> CreateOrder(int orderId)
        {
            try
            {
                // Validate and get order
                var order = await _orderService.GetOrderByIdAsync(orderId);
                var orderDto = await _dbContext.OrderDtos.GetByIdAsync(orderId, true);
                if (order == null)
                {
                    return Json(new { success = false, message = "Order not found" });
                }
                if (orderDto == null)
                {
                    return Json(new { success = false, message = "OrderDTO not found" });
                }

                if (orderDto.DateOfReceipt == null)
                {
                    return Json(new { success = false, message = "Ki kell tölteni az átvétel idejét." });
                }

                // Validate and get customer
                var customer = await _customerService.GetCustomerByIdAsync(orderDto.CustomerId);
                if (customer == null)
                {
                    return Json(new { success = false, message = "Customer not found" });
                }

                // Get and validate billing address
                var billingAddress = await _customerService.GetCustomerBillingAddressAsync(customer);
                if (billingAddress == null)
                {
                    return Json(new { success = false, message = "Billing address not found" });
                }

                //get tax info from attributes and sync with VatNumber
                if(customer.VatNumber == null || customer.VatNumber == "")
                {
                    await SynchronizeTaxInformationAsync(customer);
                }

                var billingCountry = await _countryService.GetCountryByAddressAsync(billingAddress);
                var billingCountryCode = billingCountry?.TwoLetterIsoCode ?? "HU";

                // Get shipping address (fallback to billing if not found)
                var shippingAddress = await _customerService.GetCustomerShippingAddressAsync(customer) ?? billingAddress;
                var shippingCountry = await _countryService.GetCountryByAddressAsync(shippingAddress);
                var shippingCountryCode = shippingCountry?.TwoLetterIsoCode ?? billingCountryCode;

                string megjegyzes = string.Empty;



                // Create order request
                var orderRequest = new OrderCreateRequest
                {
                    VevoNev = customer.Company ?? string.Empty,
                    VevoIrsz = billingAddress.ZipPostalCode ?? string.Empty,
                    VevoTelep = billingAddress.City ?? string.Empty,
                    VevoUtcaHsz = $"{billingAddress.Address1} {billingAddress.Address2}".Trim(),
                    VevoOrszag = billingCountryCode,
                    VevoAdoszam = customer.VatNumber,
                    MegrendelestombID = 1,
                    MegrendelesKelte = ((DateTime)orderDto.DateOfReceipt).ToLocalTime(),
                    Hatarido = DateTime.Now.AddDays(7),
                    Devizanem = "Ft", // TODO: get real default - A.
                    //FizetesiMod = order.PaymentMethodSystemName ?? "átutalás",
                    FizetesiMod = "átutalás",
                    //Email = customer.Email ?? string.Empty,
                    Email = billingAddress.Email ?? customer.Email ?? string.Empty,
                    Telefon = billingAddress.PhoneNumber ?? string.Empty,
                    MegrendelesSzamStr = orderDto.Id.ToString(),
                    Megjegyzes = $""
                };

                // Add shipping address details
                orderRequest.SzallNev = $"{shippingAddress.FirstName} {shippingAddress.LastName}".Trim();
                orderRequest.SzallIrsz = shippingAddress.ZipPostalCode ?? string.Empty;
                orderRequest.SzallTelep = shippingAddress.City ?? string.Empty;
                orderRequest.SzallUtcaHsz = $"{shippingAddress.Address1} {shippingAddress.Address2}".Trim();
                orderRequest.SzallOrszag = shippingCountryCode;

                // Get and validate order items
                var orderItems = await _dbContext.OrderItemDtos.GetAllByOrderId(order.Id, true).ToListAsync();

                if (orderItems == null || orderItems.Count == 0)
                {
                    return Json(new { success = false, message = "Order has no items" });
                }

                // Add order items
                foreach (var item in orderItems)
                {
                    var product = _dbContext.ProductDtos.GetById(item.ProductId);
                    var productName = product?.Name ?? "Product";

                    if (item.IsMeasurable)
                    {
                        // For measurable products, quantity is weight stored in NetWeight
                        orderRequest.AddItem(new InnVoiceOrderItem
                        {
                            TetelNev = productName,
                            AfaSzoveg = "27%", // TODO: Configure VAT rate dynamically
                            Brutto = true,
                            EgysegAr = item.UnitPriceInclTax,
                            Mennyiseg = item.NetWeight > 0 ? Convert.ToDecimal(item.NetWeight) : 0,
                            MennyisegEgyseg = "kg",
                            CikkSzam = string.Empty
                        });
                    }
                    else
                    {
                        orderRequest.AddItem(new InnVoiceOrderItem
                        {
                            TetelNev = productName,
                            AfaSzoveg = "27%", // TODO: Configure VAT rate dynamically
                            Brutto = true,
                            EgysegAr = item.UnitPriceInclTax,
                            Mennyiseg = item.Quantity,
                            MennyisegEgyseg = "kt",
                            CikkSzam = string.Empty
                        });
                    }

                    if(item.UnitPriceInclTax != product.Price)
                    {
                        megjegyzes += $"{productName} egységár módosítva: {Math.Round(product.Price, 2)} Ft -> {Math.Round(item.UnitPriceInclTax, 2)} Ft; \n";
                        megjegyzes += $"Kedvezmény: { ((1 - (item.UnitPriceInclTax / product.Price)) * 100).ToString() }%; \n";
                    }
                }

                orderRequest.Megjegyzes = megjegyzes;

                // Create order via API
                var response = await _innVoiceOrderService.CreateOrderAsync(orderRequest);

                if (response == null)
                {
                    return Json(new { success = false, message = "No response from InnVoice API" });
                }

                if (response.IsSuccess)
                {
                    var currentStore = await _storeContext.GetCurrentStoreAsync();
                    var storeId = currentStore?.Id ?? 0;

                    // Save InnVoice order details as attributes
                    //await _fruitBankAttributeService.InsertOrUpdateGenericAttributeAsync<Order, string>(
                    //    order.Id,
                    //    "InnVoiceOrderTechId",
                    //    response.TechId,
                    //    storeId
                    //);
                    await _genericAttributeService.SaveAttributeAsync(
                        order,
                        "InnVoiceOrderTechId",
                        response.TechId,
                        storeId
                    );

                    await _genericAttributeService.SaveAttributeAsync(
                        order,
                        "InnVoiceOrderTableId",
                        response.TableId?.ToString() ?? string.Empty,
                        storeId
                    );

                    await _genericAttributeService.SaveAttributeAsync(
                        order,
                        "InnVoiceOrderPrintLink",
                        response.PrintUrl?.ToString() ?? string.Empty,
                        storeId
                    );

                    return Json(new
                    {
                        success = true,
                        message = "Order created successfully in InnVoice",
                        data = new
                        {
                            tableId = response.TableId,
                            techId = response.TechId,
                            printUrl = response.PrintUrl
                        }
                    });
                }

                return Json(new
                {
                    success = false,
                    message = $"InnVoice API Error: {response.Message ?? "Unknown error"}"
                });
            }
            catch (Exception ex)
            {
                // Log the exception here
                // _logger.LogError(ex, "Error creating order {OrderId} in InnVoice", orderId);

                return Json(new
                {
                    success = false,
                    message = $"Error: {ex.Message}"
                });
            }
        }

        /// <summary>
        /// Get InnVoice order status for a NopCommerce order
        /// </summary>
        /// <summary>
        /// Get InnVoice order status for a NopCommerce order
        /// </summary>
        [HttpGet]
        public async Task<IActionResult> GetOrderStatus(int orderId)
        {
            try
            {
                var order = await _orderService.GetOrderByIdAsync(orderId);
                if (order == null)
                    return Json(new { success = false, message = "Order not found" });

                var storeId = (await _storeContext.GetCurrentStoreAsync()).Id;

                // Get saved InnVoice order TechId
                var techId = await _genericAttributeService.GetAttributeAsync<string>(
                    order,
                    "InnVoiceOrderTechId",
                    storeId
                );

                var printLink = await _genericAttributeService.GetAttributeAsync<string>(
                    order,
                    "InnVoiceOrderPrintLink",
                    storeId
                );

                if (string.IsNullOrEmpty(techId))
                {
                    return Json(new
                    {
                        success = false,
                        message = "No InnVoice order found for this order"
                    });
                }

                // Fetch the order details from InnVoice API using TechId
                var innVoiceOrders = await _innVoiceOrderService.GetOrderByTechIdAsync(techId);

                if (innVoiceOrders == null || innVoiceOrders.Count == 0)
                {
                    return Json(new
                    {
                        success = false,
                        message = "Order not found in InnVoice"
                    });
                }

                var innVoiceOrder = innVoiceOrders.FirstOrDefault();

                return Json(new
                {
                    success = true,
                    data = new
                    {
                        tableId = innVoiceOrder.TableId,
                        techId = innVoiceOrder.TechId,
                        printUrl = printLink,
                        customerName = innVoiceOrder.CustomerName,
                        totalGross = innVoiceOrder.TotalGross,
                        currency = innVoiceOrder.Currency,
                        orderDate = innVoiceOrder.OrderDate
                    }
                });
            }
            catch (Exception ex)
            {
                return Json(new
                {
                    success = false,
                    message = $"Error: {ex.Message}"
                });
            }
        }

        /// <summary>
        /// Create multiple orders in InnVoice from multiple NopCommerce orders
        /// </summary>
        [HttpPost]
        [IgnoreAntiforgeryToken]
        public async Task<IActionResult> CreateMultipleOrders([FromBody] int[] orderIds)
        {
            try
            {
                if (orderIds == null || orderIds.Length == 0)
                    return Json(new { success = false, message = "No order IDs provided" });

                var orderRequests = new List<OrderCreateRequest>();

                foreach (var orderId in orderIds)
                {
                    var order = await _orderService.GetOrderByIdAsync(orderId);
                    if (order == null)
                        continue;

                    var customer = await _customerService.GetCustomerByIdAsync(order.CustomerId);
                    var billingAddress = await _customerService.GetCustomerBillingAddressAsync(customer);

                    if (billingAddress == null)
                        continue;

                    var billingCountry = await _countryService.GetCountryByAddressAsync(billingAddress);
                    var billingCountryCode = billingCountry?.TwoLetterIsoCode ?? "HU";

                    var orderRequest = new OrderCreateRequest
                    {
                        VevoNev = $"{billingAddress.FirstName} {billingAddress.LastName}",
                        VevoIrsz = billingAddress.ZipPostalCode ?? "",
                        VevoTelep = billingAddress.City ?? "",
                        VevoUtcaHsz = $"{billingAddress.Address1} {billingAddress.Address2}".Trim(),
                        VevoOrszag = billingCountryCode,
                        MegrendelestombID = 1,
                        MegrendelesKelte = order.CreatedOnUtc.ToLocalTime(),
                        Hatarido = DateTime.Now.AddDays(7),
                        Devizanem = "Ft",
                        FizetesiMod = order.PaymentMethodSystemName,
                        Email = billingAddress.Email,
                        Telefon = billingAddress.PhoneNumber,
                        MegrendelesSzamStr = order.Id.ToString(),
                        Megjegyzes = $""
                    };

                    // Add order items
                    var orderItems = await _orderService.GetOrderItemsAsync(order.Id);
                    foreach (var item in orderItems)
                    {
                        var product = await _productService.GetProductByIdAsync(item.ProductId);

                        orderRequest.AddItem(new InnVoiceOrderItem
                        {
                            TetelNev = product?.Name ?? "Product",
                            AfaSzoveg = "27%",
                            Brutto = true,
                            EgysegAr = item.UnitPriceInclTax,
                            Mennyiseg = item.Quantity,
                            MennyisegEgyseg = "db",
                            CikkSzam = product?.Sku
                        });
                    }

                    orderRequests.Add(orderRequest);
                }

                if (orderRequests.Count == 0)
                    return Json(new { success = false, message = "No valid orders to create" });

                // Create orders via API
                var responses = await _innVoiceOrderService.CreateOrdersAsync(orderRequests);

                if (responses != null)
                {
                    var successCount = responses.Count(r => r.IsSuccess);
                    var failureCount = responses.Count - successCount;

                    // Save TechIds for successful orders
                    var storeId = (await _storeContext.GetCurrentStoreAsync()).Id;
                    for (int i = 0; i < responses.Count && i < orderIds.Length; i++)
                    {
                        if (responses[i].IsSuccess)
                        {
                            var order = await _orderService.GetOrderByIdAsync(orderIds[i]);
                            if (order != null)
                            {
                                await _genericAttributeService.SaveAttributeAsync(
                                    order,
                                    "InnVoiceOrderTechId",
                                    responses[i].TechId,
                                    storeId
                                );

                                await _genericAttributeService.SaveAttributeAsync(
                                    order,
                                    "InnVoiceOrderTableId",
                                    responses[i].TableId?.ToString(),
                                    storeId
                                );
                            }
                        }
                    }

                    return Json(new
                    {
                        success = successCount > 0,
                        message = $"Created {successCount} orders successfully. {failureCount} failed.",
                        data = new
                        {
                            successCount,
                            failureCount,
                            responses = responses.Select(r => new
                            {
                                success = r.IsSuccess,
                                tableId = r.TableId,
                                techId = r.TechId,
                                message = r.Message,
                                printUrl = r.PrintUrl
                            })
                        }
                    });
                }
                else
                {
                    throw new Exception($"InvoiceOrderAPi invalid response");
                }
            }
            catch (Exception ex)
            {
                return Json(new
                {
                    success = false,
                    message = $"Error: {ex.Message}"
                });
            }
        }

        private async Task SynchronizeTaxInformationAsync(Customer customer)
        {
            string attributesXml = customer.CustomCustomerAttributesXML;

            string taxId = null;

            if (!string.IsNullOrWhiteSpace(attributesXml))
            {
                var doc = XDocument.Parse(attributesXml);
                taxId = doc.Descendants("CustomerAttribute")
                           .FirstOrDefault(el => (int?)el.Attribute("ID") == 1) // your TaxId attribute ID
                           ?.Descendants("Value")
                           .FirstOrDefault()
                           ?.Value;
            }

            if (!string.IsNullOrWhiteSpace(taxId) && string.IsNullOrWhiteSpace(customer.VatNumber))
            {
                customer.VatNumber = taxId;
            }
            else if (string.IsNullOrWhiteSpace(taxId) && !string.IsNullOrWhiteSpace(customer.VatNumber))
            {
                await _fruitBankAttributeService.InsertOrUpdateGenericAttributeAsync<Customer, string>(
                    customer.Id,
                    "TaxId",
                    customer.VatNumber);
            }

            _dbContext.Customers.Update(customer, false);
        }


    }
}
