using AyCode.Core.Enums;
using AyCode.Core.Extensions;
using AyCode.Core.Loggers;
using FruitBank.Common;
using FruitBank.Common.Dtos;
using FruitBank.Common.Entities;
using FruitBank.Common.Loggers;
using FruitBankHybrid.Shared.Services.SignalRs;
using Newtonsoft.Json;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Payments;
using System.Linq.Expressions;
using System.Runtime.Serialization;
using AyCode.Core.Serializers.Toons;

namespace FruitBankHybrid.Shared.Tests;

[TestClass]
public sealed class OrderClientTests
{
    private const int CustomerIdAasdDsserverCom = 6; //aasd@dsserver.com

    private FruitBankSignalRClient _signalRClient = null!;

    [TestInitialize]
    public void TestInit()
    {
        if (!FruitBankConstClient.BaseUrl.Contains("localhost:")) throw new Exception("NEM LOCALHOST-ON TESZTELÜNK!");

        _signalRClient = TestSignalRClientFactory.Create(nameof(OrderClientTests));
    }


    [TestMethod]
    public async Task GetAllStockTakings()
    {
        var stockTakings = await _signalRClient.GetStockTakings(true);

        Assert.IsNotNull(stockTakings);
        Assert.IsNotEmpty(stockTakings);

        Assert.IsTrue(stockTakings.All(o => o.StockTakingItems != null));
        Assert.IsTrue(stockTakings.All(o => o.StockTakingItems!.All(oi => oi.Product != null && oi.Product.Id == oi.ProductId)));
    }

    [TestMethod]
    public async Task GetAllStockTakingItems()
    {
        var stockTakingItems = await _signalRClient.GetStockTakingItems();

        Assert.IsNotNull(stockTakingItems);
        Assert.IsNotEmpty(stockTakingItems);

        Assert.IsTrue(stockTakingItems.All(oi => oi is { StockTaking: not null, Product: not null } && oi.Product.Id == oi.ProductId));
    }

    [TestMethod]
    public async Task GetAllStockTakingItemById()
    {
        var stockTakingItem = await _signalRClient.GetStockTakingItemsById(100);

        Assert.IsNotNull(stockTakingItem);
        Assert.IsNotNull(stockTakingItem.Product);
        Assert.IsNotNull(stockTakingItem.StockTaking);
    }

    [TestMethod]
    public async Task GetAllOrderDtos()
    {
        var orderDtos = await _signalRClient.GetAllOrderDtos();

        Assert.IsNotNull(orderDtos);
        Assert.IsTrue(orderDtos.Count != 0);

        Assert.IsTrue(orderDtos.All(o => o.OrderItemDtos.All(oi => oi.ProductDto != null && oi.ProductDto.Id == oi.ProductId)));
    }

    [TestMethod]
    public async Task GetAllOrderDtosByFilter()
    {
        //Queryable? filter = dto => dto.Id == 15;
        var orderDtos = await _signalRClient.GetAllOrderDtos();

        Assert.IsNotNull(orderDtos);
        Assert.IsTrue(orderDtos.Count != 0);

        Assert.IsTrue(orderDtos.All(o => o.OrderItemDtos.All(oi => oi.ProductDto != null && oi.ProductDto.Id == oi.ProductId)));
    }

    [TestMethod]
    [DataRow(1)]
    [DataRow(2)]
    [DataRow(3)]
    public async Task GetOrderDtoById(int orderId)
    {
        var orderDto = await _signalRClient.GetOrderDtoById(orderId);

        Assert.IsNotNull(orderDto);

        Assert.IsTrue(orderDto.OrderStatusId >= 10);
        Assert.IsTrue(orderDto.CustomOrderNumber == orderId.ToString());
    }

    [TestMethod]
    public async Task GetPendingOrderDtos()
    {
        var initialCount = 28;
        List<OrderDto>? pendingOrderDtos = (await _signalRClient.GetPendingOrderDtos())?.Take(initialCount).ToList();

        Assert.IsNotNull(pendingOrderDtos);

        // Másolat létrehozása a frissítendő adatok generálásához
        List<OrderDto>? pendingOrderDtos2 = pendingOrderDtos.ToList();

        Assert.IsNotNull(pendingOrderDtos2);
        Assert.AreEqual(initialCount, pendingOrderDtos2.Count);

        // ÚJ BEÁLLÍTÁSOK A RESOLVER-REL ÉS CONTEXT-EL
        //var settings = new JsonSerializerSettings
        //{
        //    ContractResolver = new UnifiedMergeContractResolver(),
        //    ObjectCreationHandling = ObjectCreationHandling.Replace,
        //    Context = new StreamingContext(StreamingContextStates.All, new Dictionary<object, object>()),

        //    // Alapvető beállítások
        //    PreserveReferencesHandling = PreserveReferencesHandling.Objects,
        //    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
        //    NullValueHandling = NullValueHandling.Ignore,
        //};

        var dtNow = DateTime.UtcNow;

        // Eredeti objektum referenciájának eltárolása
        var orderDto1 = pendingOrderDtos[0];

        // Frissítjük a másolatot
        pendingOrderDtos2[0].PaidDateUtc = dtNow;
        pendingOrderDtos2[0].GenericAttributes[0].CreatedOrUpdatedDateUTC = dtNow;

        pendingOrderDtos2.CopyTo(pendingOrderDtos);
        // Szerializálás a Merge Resolverrel
        //var json = pendingOrderDtos2.ToJson(settings);

        //Assert.IsTrue(json.Contains("$id"));
        //Assert.IsTrue(json.Contains("$ref"));

        //pendingOrderDtos.DeepPopulateWithMerge(json, settings);

        Assert.IsTrue(pendingOrderDtos.Count == pendingOrderDtos2.Count, $"A listák méretének egyeznie kell: {pendingOrderDtos.Count} != {pendingOrderDtos2.Count}");

        Assert.IsTrue(orderDto1.PaidDateUtc == dtNow, "A PaidDateUtc mezőnek frissülnie kellett a Merge során.");
        Assert.IsTrue(orderDto1.GenericAttributes[0].CreatedOrUpdatedDateUTC == dtNow, "A beágyazott GenericAttribute dátumának frissülnie kellett.");

        Assert.IsTrue(pendingOrderDtos.All(o => o.OrderStatus == OrderStatus.Pending));
        Assert.IsTrue(pendingOrderDtos.Count != 0);
    }

    [TestMethod]
    public async Task GetPendingOrderDtosForMeasuring()
    {
        var orderDtosForMeasuring = await _signalRClient.GetPendingOrderDtosForMeasuring(9999);

        Assert.IsNotNull(orderDtosForMeasuring);
        //Assert.IsTrue(orderDtosForMeasuring.Any(x=>x.Id ==51));
        Assert.IsTrue(orderDtosForMeasuring.All(o => o.PaymentStatus < PaymentStatus.Paid));
        Assert.IsTrue(orderDtosForMeasuring.Count != 0);
    }

    [TestMethod]
    [DataRow(new[] { 1, 2, 4, 7 })]
    public async Task GetOrderDtoByIds(int[] orderIds)
    {
        var orderDtoList = await _signalRClient.GetAllOrderDtoByIds(orderIds);

        Assert.IsNotNull(orderDtoList);

        Assert.IsTrue(orderDtoList.Count == orderIds.Length);
        Assert.IsTrue(orderDtoList.All(x => orderIds.Contains(x.Id)));
    }
}