using static AyCode.Core.Tests.TestModels.AcSerializerModels;

namespace AyCode.Core.Tests.Serialization;

/// <summary>
/// Helper methods for creating test data in serializer tests.
/// </summary>
public static class AcSerializerTestHelper
{
    public static List<TestClassWithLongPropertyNames> CreateLongPropertyNameItems(int count)
    {
        return Enumerable.Range(0, count).Select(i => new TestClassWithLongPropertyNames
        {
            FirstProperty = $"Value1_{i}",
            SecondProperty = $"Value2_{i}",
            ThirdProperty = $"Value3_{i}",
            FourthProperty = $"Value4_{i}"
        }).ToList();
    }

    public static List<TestClassWithMixedStrings> CreateMixedStringItems(int count)
    {
        return Enumerable.Range(0, count).Select(i => new TestClassWithMixedStrings
        {
            Id = i,
            ShortName = $"A{i % 3}",
            LongName = $"LongName_{i % 5}",
            Description = $"Description_value_{i % 7}",
            Tag = i % 2 == 0 ? "AB" : "XY"
        }).ToList();
    }

    public static TestNestedStructure CreateNestedStructure(int level1Count, int level2Count)
    {
        return new TestNestedStructure
        {
            RootName = "RootObject",
            Level1Items = Enumerable.Range(0, level1Count).Select(i => new TestLevel1
            {
                Level1Name = $"Level1_{i}",
                Level2Items = Enumerable.Range(0, level2Count).Select(j => new TestLevel2
                {
                    Level2Name = $"Level2_{i}_{j}",
                    Value = $"Value_{i * level2Count + j}"
                }).ToList()
            }).ToList()
        };
    }

    public static List<TestClassWithRepeatedValues> CreateRepeatedValueItems(int count)
    {
        return Enumerable.Range(0, count).Select(i => new TestClassWithRepeatedValues
        {
            Id = i,
            Status = i % 3 == 0 ? "Pending" : i % 3 == 1 ? "Processing" : "Completed",
            Category = i % 5 == 0 ? "CategoryA" : i % 5 == 1 ? "CategoryB" : "CategoryC",
            Priority = i % 2 == 0 ? "High" : "Low_Priority_Value"
        }).ToList();
    }

    public static List<TestClassWithNameValue> CreateNameValueItems(int uniqueCount, int reuseCount)
    {
        var items = new List<TestClassWithNameValue>();

        for (int i = 0; i < uniqueCount; i++)
        {
            items.Add(new TestClassWithNameValue
            {
                Name = $"UniqueName_{i:D4}",
                Value = $"UniqueValue_{i:D4}"
            });
        }

        for (int i = 0; i < reuseCount; i++)
        {
            items.Add(new TestClassWithNameValue
            {
                Name = $"UniqueName_{i % 10:D4}",
                Value = $"UniqueValue_{(i + 10) % uniqueCount:D4}"
            });
        }

        return items;
    }

    public static List<TestClassWithNullableStrings> CreateNullableStringItems(int count)
    {
        return Enumerable.Range(0, count).Select(i => new TestClassWithNullableStrings
        {
            Id = i,
            RequiredName = $"Required_{i:D3}",
            OptionalName = i % 3 == 0 ? null : i % 3 == 1 ? "" : $"Optional_{i:D3}",
            Description = i % 2 == 0 ? $"Description_{i % 5:D3}" : null
        }).ToList();
    }

    public static List<TestCustomerLikeDto> CreateCustomerLikeItems(int count)
    {
        return Enumerable.Range(0, count).Select(i => new TestCustomerLikeDto
        {
            Id = i,
            FirstName = $"FirstName_{i % 10}",
            LastName = $"LastName_{i % 8}",
            Email = $"user{i}@example.com",
            Company = $"Company_{i % 5}",
            Department = i % 3 == 0 ? "Sales" : i % 3 == 1 ? "Engineering" : "Marketing",
            Role = i % 4 == 0 ? "Admin" : i % 4 == 1 ? "User" : i % 4 == 2 ? "Manager" : "Guest",
            Status = i % 2 == 0 ? "Active" : "Inactive",
            Attributes =
            [
                new() { Key = "DateOfReceipt", Value = $"{i % 28 + 1}/24/2025 00:27:00" },
                new() { Key = "Priority", Value = (i % 5).ToString() },
                new() { Key = "CustomField1", Value = $"CustomValue_{i % 7}" },
                new() { Key = "CustomField2", Value = i % 2 == 0 ? "Yes" : "No_Value" }
            ]
        }).ToList();
    }

    public static List<TestHighReuseDto> CreateHighReuseItems(int count)
    {
        return Enumerable.Range(0, count).Select(i => new TestHighReuseDto
        {
            Id = i,
            CategoryCode = $"CAT_{i % 10:D2}",
            StatusCode = $"STATUS_{i % 5:D2}",
            TypeCode = $"TYPE_{i % 3:D2}",
            PriorityCode = i % 2 == 0 ? "PRIORITY_HIGH" : "PRIORITY_LOW",
            UniqueField = $"UNIQUE_{i:D4}"
        }).ToList();
    }

    public static List<TestClassWithNullableProperties> CreateNullablePropertyItems(int count)
    {
        return Enumerable.Range(1, count).Select(i => new TestClassWithNullableProperties
        {
            Id = i,
            NullableInt = i % 3 == 0 ? null : i * 10,
            NullableDouble = i % 2 == 0 ? null : i * 1.5,
            NullableDateTime = i % 4 == 0 ? null : DateTime.UtcNow.AddDays(-i),
            NullableGuid = i % 5 == 0 ? null : Guid.NewGuid()
        }).ToList();
    }

    public static TestStockTaking CreateStockTaking(int itemCount = 2, int palletCount = 2)
    {
        return new TestStockTaking
        {
            Id = 1,
            StartDateTime = DateTime.UtcNow,
            IsClosed = false,
            Creator = 100,
            Created = DateTime.UtcNow.AddHours(-2),
            Modified = DateTime.UtcNow,
            StockTakingItems = Enumerable.Range(1, itemCount).Select(i => new TestStockTakingItem
            {
                Id = i * 10,
                StockTakingId = 1,
                ProductId = 500 + i,
                IsMeasured = i % 2 == 0,
                OriginalStockQuantity = 50 * i,
                MeasuredStockQuantity = 48 * i,
                Created = DateTime.UtcNow.AddHours(-i),
                Modified = DateTime.UtcNow,
                StockTakingItemPallets = Enumerable.Range(1, palletCount).Select(p => new TestStockTakingItemPallet
                {
                    Id = i * 100 + p,
                    StockTakingItemId = i * 10,
                    TrayQuantity = p + 2,
                    TareWeight = p * 0.5,
                    PalletWeight = p * 10.0,
                    GrossWeight = p * 50.0,
                    IsMeasured = p % 2 == 0,
                    CreatorId = p % 2 == 0 ? 100 : null,
                    ModifierId = p % 2 == 1 ? 200 : null,
                    Created = DateTime.UtcNow,
                    Modified = DateTime.UtcNow
                }).ToList()
            }).ToList()
        };
    }

    public static List<TestStockTaking> CreateStockTakingList(int count, int itemsPerStock = 1, int palletsPerItem = 1)
    {
        return Enumerable.Range(1, count).Select(s => new TestStockTaking
        {
            Id = s,
            StartDateTime = DateTime.UtcNow.AddDays(-s),
            IsClosed = s % 2 == 0,
            Creator = s,
            Created = DateTime.UtcNow.AddDays(-s),
            Modified = DateTime.UtcNow,
            StockTakingItems = Enumerable.Range(1, itemsPerStock).Select(i => new TestStockTakingItem
            {
                Id = s * 100 + i,
                StockTakingId = s,
                ProductId = 1000 * s + i,
                IsMeasured = i % 2 == 0,
                OriginalStockQuantity = 10 * i,
                MeasuredStockQuantity = 10 * i,
                Created = DateTime.UtcNow,
                Modified = DateTime.UtcNow,
                StockTakingItemPallets = Enumerable.Range(1, palletsPerItem).Select(p => new TestStockTakingItemPallet
                {
                    Id = s * 1000 + i * 100 + p,
                    StockTakingItemId = s * 100 + i,
                    CreatorId = p % 2 == 0 ? s * 10 : null,
                    ModifierId = p % 2 == 1 ? s * 20 : null,
                    TrayQuantity = p,
                    TareWeight = p * 1.0,
                    PalletWeight = p * 10.0,
                    GrossWeight = p * 50.0,
                    IsMeasured = p % 2 == 0,
                    Created = DateTime.UtcNow,
                    Modified = DateTime.UtcNow
                }).ToList()
            }).ToList()
        }).ToList();
    }

    public static List<TestEntityWithDateTimeAndInt> CreateDateTimeEntities(int count)
    {
        return Enumerable.Range(1, count).Select(i => new TestEntityWithDateTimeAndInt
        {
            Id = i,
            IntValue = i * 10,
            Created = DateTime.UtcNow.AddDays(-i),
            Modified = DateTime.UtcNow.AddHours(-i),
            StatusCode = i % 5,
            Name = $"Entity_{i}"
        }).ToList();
    }

    public static List<TestParentWithDateTimeItemCollection> CreateParentWithDateTimeItems(int parentCount, int itemsPerParent)
    {
        return Enumerable.Range(1, parentCount).Select(p => new TestParentWithDateTimeItemCollection
        {
            Id = p,
            Name = $"Parent_{p}",
            Created = DateTime.UtcNow.AddDays(-p * 10),
            Items = Enumerable.Range(1, itemsPerParent).Select(i => new TestEntityWithDateTimeAndInt
            {
                Id = p * 100 + i,
                IntValue = i * 10,
                Created = DateTime.UtcNow.AddDays(-i),
                Modified = DateTime.UtcNow.AddHours(-i),
                StatusCode = i % 3,
                Name = $"Parent{p}_Item_{i}"
            }).ToList()
        }).ToList();
    }
}
