using foodmarket.Application.Inventory;
using foodmarket.Domain.Catalog;
using foodmarket.Domain.Inventory;
using foodmarket.Domain.Purchases;
using foodmarket.Domain.Sales;
using foodmarket.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;

namespace foodmarket.Api.Seed;

/// <summary>Заполняет КОНКРЕТНОГО tenant'а реалистичными демо-данными для
/// показа стенда: 5 групп / 50 товаров / 10 контрагентов / 5 приёмок (Posted)
/// / 30 розничных продаж (Posted) / 1 опт. отгрузка / 1 списание / 1 перемещение
/// / 1 инвентаризация. Идемпотентен: маркер — наличие любого Product с
/// Article startsWith "DEMO-" в этой org. Повторный вызов возвращает summary
/// без повторных вставок.
///
/// Запускается через POST /api/admin/seed-demo (см. DemoSeedController).
/// Внутри одной транзакции; на стейдже занимает 2-5 секунд.</summary>
public sealed class DemoTenantSeeder
{
    private readonly AppDbContext _db;
    private readonly IStockService _stock;
    private readonly Random _rng = new(42); // детерминированно для воспроизводимости

    public DemoTenantSeeder(AppDbContext db, IStockService stock)
    {
        _db = db;
        _stock = stock;
    }

    public sealed record SeedSummary(
        bool AlreadySeeded,
        int Groups, int Products, int Counterparties,
        int Supplies, int Sales, int Demands, int Losses, int Transfers, int Inventories,
        int Stores);

    public async Task<SeedSummary> SeedAsync(Guid orgId, CancellationToken ct = default)
    {
        // Idempotency marker: artikul DEMO-* (включает и фолбэк DEMO-{group}-NN).
        var alreadySeeded = await _db.Products.IgnoreQueryFilters()
            .AnyAsync(p => p.OrganizationId == orgId && p.Article != null && p.Article.StartsWith("DEMO-"), ct);
        if (alreadySeeded)
        {
            // Возвращаем какие данные уже есть, чтобы UI мог показать summary.
            return await CountExistingAsync(orgId, ct);
        }

        await using var tx = await _db.Database.BeginTransactionAsync(ct);

        // ── Подтянем системные ссылки ───────────────────────────────────────
        var unitKg = await _db.UnitsOfMeasure.IgnoreQueryFilters().FirstAsync(u => u.OrganizationId == null && u.Code == "166", ct);
        var unitSht = await _db.UnitsOfMeasure.IgnoreQueryFilters().FirstAsync(u => u.OrganizationId == null && u.Code == "796", ct);
        var unitL = await _db.UnitsOfMeasure.IgnoreQueryFilters().FirstAsync(u => u.OrganizationId == null && u.Code == "112", ct);
        var retailPrice = await _db.PriceTypes.IgnoreQueryFilters().FirstAsync(p => p.OrganizationId == orgId && p.IsRetail, ct);
        var currency = await _db.Currencies.FirstAsync(c => c.Code == "KZT", ct);
        var orgRoot = await _db.ProductGroups.IgnoreQueryFilters()
            .FirstOrDefaultAsync(g => g.OrganizationId == orgId && g.ParentId == null, ct);

        // ── Магазины: основной уже есть из bootstrap'а; делаем второй для transfer'а ──
        var stores = await _db.Stores.IgnoreQueryFilters()
            .Where(s => s.OrganizationId == orgId).ToListAsync(ct);
        var mainStore = stores.First(s => s.IsMain);
        var secondStore = stores.FirstOrDefault(s => !s.IsMain);
        if (secondStore is null)
        {
            secondStore = new Store
            {
                OrganizationId = orgId, Name = "Склад резерв", Code = "RESERVE",
                Address = "Алматы, Тестовая 2", IsMain = false, IsActive = true,
            };
            _db.Stores.Add(secondStore);
        }

        // ── Группы товаров (5 категорий) ────────────────────────────────────
        var grpNames = new[] { "Молочные продукты", "Хлеб и выпечка", "Напитки", "Бакалея", "Снеки" };
        var groups = new List<ProductGroup>();
        foreach (var name in grpNames)
        {
            var g = new ProductGroup
            {
                OrganizationId = orgId, Name = name, ParentId = null,
                Path = name, SortOrder = 10, MarkupPercent = 30m,
            };
            _db.ProductGroups.Add(g);
            groups.Add(g);
        }

        // ── 50 товаров (по 10 на группу) ────────────────────────────────────
        var productTemplates = BuildProductCatalog();
        var products = new List<Product>();
        var barcodeSeq = 200_000_000_001L;
        for (int g = 0; g < groups.Count; g++)
        {
            for (int i = 0; i < 10; i++)
            {
                var t = productTemplates[g][i];
                var unit = t.Unit == "kg" ? unitKg : t.Unit == "l" ? unitL : unitSht;
                var packaging = t.Unit == "kg" ? Packaging.Weight : t.Unit == "l" ? Packaging.Liquid : Packaging.Piece;
                var article = $"DEMO-{g + 1:D2}-{i + 1:D2}";
                var product = new Product
                {
                    OrganizationId = orgId,
                    Name = t.Name,
                    Article = article,
                    Description = null,
                    UnitOfMeasureId = unit.Id,
                    Vat = 16m, VatEnabled = true,
                    ProductGroupId = groups[g].Id,
                    Packaging = packaging,
                    ReferencePrice = t.RetailPrice,
                    Prices = new List<ProductPrice>
                    {
                        new ProductPrice
                        {
                            OrganizationId = orgId,
                            PriceTypeId = retailPrice.Id,
                            Amount = t.RetailPrice,
                            CurrencyId = currency.Id,
                        },
                    },
                    Barcodes = new List<ProductBarcode>
                    {
                        new ProductBarcode
                        {
                            OrganizationId = orgId,
                            Code = MakeEan13(barcodeSeq++),
                            Type = BarcodeType.Ean13, IsPrimary = true,
                        },
                    },
                };
                _db.Products.Add(product);
                products.Add(product);
            }
        }

        // ── 10 контрагентов (5 поставщиков + 5 покупателей-юрлиц) ───────────
        var counterparties = new List<Counterparty>();
        var supplierNames = new[] { "ТОО «Алматы Фуд»", "ТОО «Карагандинский молокозавод»", "ИП Бегимбаев К.Т.", "ТОО «Хлебокомбинат Астана»", "ТОО «Шымкент Дистрибьюшн»" };
        var customerNames = new[] { "ТОО «Сеть кафе Бариста»", "ТОО «Школа-лицей №5»", "ТОО «Гостиница Алтын»", "ТОО «Корпоративное питание KZ»", "ТОО «Сеть пекарен Самал»" };
        foreach (var name in supplierNames)
        {
            counterparties.Add(new Counterparty
            {
                OrganizationId = orgId, Name = name, LegalName = name,
                Type = CounterpartyType.LegalEntity,
                Bin = NextBin(barcodeSeq++),
                Phone = $"+7 (727) 1{_rng.Next(10, 99)}-{_rng.Next(10, 99)}-{_rng.Next(10, 99)}",
                Notes = "DEMO supplier",
            });
        }
        foreach (var name in customerNames)
        {
            counterparties.Add(new Counterparty
            {
                OrganizationId = orgId, Name = name, LegalName = name,
                Type = CounterpartyType.LegalEntity,
                Bin = NextBin(barcodeSeq++),
                Phone = $"+7 (727) 2{_rng.Next(10, 99)}-{_rng.Next(10, 99)}-{_rng.Next(10, 99)}",
                Notes = "DEMO customer",
            });
        }
        _db.Counterparties.AddRange(counterparties);

        // Сохраняем сначала справочники: дальше нужны их ID для документов.
        await _db.SaveChangesAsync(ct);

        var suppliers = counterparties.Take(5).ToList();
        var customers = counterparties.Skip(5).ToList();

        // ── 5 приёмок за последние 30 дней (Posted), стоковость + Cost ──────
        var now = DateTime.UtcNow;
        var supplies = new List<Supply>();
        for (int i = 0; i < 5; i++)
        {
            var date = now.AddDays(-_rng.Next(1, 30));
            var supply = new Supply
            {
                OrganizationId = orgId,
                Number = $"П-DEMO-{i + 1:D3}",
                Date = date, Status = SupplyStatus.Posted, PostedAt = date,
                SupplierId = suppliers[i % suppliers.Count].Id,
                StoreId = mainStore.Id, CurrencyId = currency.Id,
                Notes = "DEMO",
            };
            var picked = products.OrderBy(_ => _rng.Next()).Take(_rng.Next(5, 10)).ToList();
            int order = 0;
            decimal total = 0m;
            foreach (var p in picked)
            {
                var qty = _rng.Next(20, 100);
                var price = Math.Round(p.ReferencePrice!.Value * 0.6m, 2); // закупка ~60% от розницы
                var lt = qty * price;
                supply.Lines.Add(new SupplyLine
                {
                    OrganizationId = orgId,
                    ProductId = p.Id, Quantity = qty, UnitPrice = price,
                    LineTotal = lt, SortOrder = order++,
                });
                total += lt;
                // Cost: moving average; для первого захода ставим = цена приёмки (currentQty=0).
                var currentQty = await _db.Stocks
                    .Where(s => s.ProductId == p.Id)
                    .SumAsync(s => (decimal?)s.Quantity, ct) ?? 0m;
                p.Cost = foodmarket.Application.Inventory.MovingAverageCost.Compute(currentQty, p.Cost, qty, price);
                p.LastSupplyAt = date;
                // Stock + movement
                await _stock.ApplyMovementAsync(new StockMovementDraft(
                    ProductId: p.Id, StoreId: mainStore.Id, Quantity: qty,
                    Type: MovementType.Supply, DocumentType: "supply",
                    DocumentId: supply.Id, DocumentNumber: supply.Number,
                    UnitCost: price, OccurredAt: date), ct);
            }
            supply.Total = total;
            _db.Supplies.Add(supply);
            supplies.Add(supply);
            // SaveChanges после каждой приёмки — иначе StockService при следующей
            // итерации не увидит свежесозданные Stock-строки (FirstOrDefault через
            // DbSet идёт в БД минуя ChangeTracker.Local), и упирается в 23505 по
            // unique-индексу (OrganizationId, ProductId, StoreId).
            await _db.SaveChangesAsync(ct);
        }

        // ── 30 розничных продаж (Posted), последний месяц ───────────────────
        var retailPoint = await _db.RetailPoints.IgnoreQueryFilters()
            .FirstOrDefaultAsync(rp => rp.OrganizationId == orgId, ct);
        for (int i = 0; i < 30; i++)
        {
            var date = now.AddDays(-_rng.Next(0, 28)).AddHours(-_rng.Next(0, 12));
            var sale = new RetailSale
            {
                OrganizationId = orgId,
                Number = $"ПР-DEMO-{i + 1:D3}",
                Date = date, Status = RetailSaleStatus.Posted, PostedAt = date,
                StoreId = mainStore.Id, RetailPointId = retailPoint?.Id,
                CurrencyId = currency.Id,
                Payment = (PaymentMethod)(_rng.Next(0, 2)), // Cash / Card
                IsReturn = false,
            };
            var picked = products.OrderBy(_ => _rng.Next()).Take(_rng.Next(1, 5)).ToList();
            int order = 0;
            decimal subtotal = 0;
            foreach (var p in picked)
            {
                var qty = _rng.Next(1, 4);
                var price = p.ReferencePrice!.Value;
                var lt = qty * price;
                sale.Lines.Add(new RetailSaleLine
                {
                    OrganizationId = orgId,
                    ProductId = p.Id, Quantity = qty, UnitPrice = price,
                    LineTotal = lt, Discount = 0m, VatPercent = 16m,
                    SortOrder = order++,
                });
                subtotal += lt;
                await _stock.ApplyMovementAsync(new StockMovementDraft(
                    ProductId: p.Id, StoreId: mainStore.Id, Quantity: -qty,
                    Type: MovementType.RetailSale, DocumentType: "retail-sale",
                    DocumentId: sale.Id, DocumentNumber: sale.Number,
                    UnitCost: price, OccurredAt: date), ct);
            }
            sale.Subtotal = subtotal;
            sale.DiscountTotal = 0;
            sale.Total = subtotal;
            sale.PaidCash = sale.Payment == PaymentMethod.Cash ? subtotal : 0m;
            sale.PaidCard = sale.Payment == PaymentMethod.Card ? subtotal : 0m;
            _db.RetailSales.Add(sale);
            // SaveChanges после каждой продажи: те же причины что в supplies-цикле.
            await _db.SaveChangesAsync(ct);
        }

        // ── 1 опт. отгрузка (Demand) ────────────────────────────────────────
        var demandPicked = products.OrderBy(_ => _rng.Next()).Take(3).ToList();
        var demand = new Demand
        {
            OrganizationId = orgId,
            Number = "ОПТ-DEMO-001",
            Date = now.AddDays(-7), Status = DemandStatus.Posted, PostedAt = now.AddDays(-7),
            CustomerId = customers[0].Id, StoreId = mainStore.Id, CurrencyId = currency.Id,
            Payment = DemandPayment.BankTransfer, PaidAmount = 0, Notes = "DEMO",
        };
        decimal dTot = 0;
        int dOrder = 0;
        foreach (var p in demandPicked)
        {
            var qty = _rng.Next(5, 15);
            var price = Math.Round(p.ReferencePrice!.Value * 0.85m, 2); // опт-скидка 15%
            var lt = qty * price;
            demand.Lines.Add(new DemandLine
            {
                OrganizationId = orgId,
                ProductId = p.Id, Quantity = qty, UnitPrice = price,
                LineTotal = lt, Discount = 0m, VatPercent = 16m, SortOrder = dOrder++,
            });
            dTot += lt;
            await _stock.ApplyMovementAsync(new StockMovementDraft(
                ProductId: p.Id, StoreId: mainStore.Id, Quantity: -qty,
                Type: MovementType.WholesaleSale, DocumentType: "demand",
                DocumentId: demand.Id, DocumentNumber: demand.Number,
                UnitCost: price, OccurredAt: demand.Date), ct);
        }
        demand.Subtotal = dTot;
        demand.Total = dTot;
        _db.Demands.Add(demand);

        // ── 1 списание (Loss) ──────────────────────────────────────────────
        var lossProd = products[_rng.Next(products.Count)];
        var loss = new Loss
        {
            OrganizationId = orgId,
            Number = "С-DEMO-001",
            Date = now.AddDays(-3), Status = LossStatus.Posted, PostedAt = now.AddDays(-3),
            StoreId = mainStore.Id, CurrencyId = currency.Id,
            Reason = LossReason.Expired, Notes = "DEMO — просрочка",
            Total = lossProd.Cost * 2,
        };
        loss.Lines.Add(new LossLine
        {
            OrganizationId = orgId,
            ProductId = lossProd.Id, Quantity = 2, UnitCost = lossProd.Cost,
            LineTotal = lossProd.Cost * 2, SortOrder = 0,
        });
        await _stock.ApplyMovementAsync(new StockMovementDraft(
            ProductId: lossProd.Id, StoreId: mainStore.Id, Quantity: -2,
            Type: MovementType.WriteOff, DocumentType: "loss",
            DocumentId: loss.Id, DocumentNumber: loss.Number,
            UnitCost: lossProd.Cost, OccurredAt: loss.Date), ct);
        _db.Losses.Add(loss);

        // ── 1 перемещение (Transfer): между main и second ──────────────────
        var transferProd = products[_rng.Next(products.Count)];
        var transferQty = 10;
        var transfer = new Transfer
        {
            OrganizationId = orgId,
            Number = "ПМ-DEMO-001",
            Date = now.AddDays(-5), Status = TransferStatus.Posted, PostedAt = now.AddDays(-5),
            FromStoreId = mainStore.Id, ToStoreId = secondStore.Id,
            Notes = "DEMO",
        };
        transfer.Lines.Add(new TransferLine
        {
            OrganizationId = orgId,
            TransferId = transfer.Id,
            ProductId = transferProd.Id, Quantity = transferQty, UnitCost = transferProd.Cost,
            LineTotal = transferProd.Cost * transferQty, SortOrder = 0,
        });
        transfer.Total = transferProd.Cost * transferQty;
        await _stock.ApplyMovementAsync(new StockMovementDraft(
            ProductId: transferProd.Id, StoreId: mainStore.Id, Quantity: -transferQty,
            Type: MovementType.TransferOut, DocumentType: "transfer-out",
            DocumentId: transfer.Id, DocumentNumber: transfer.Number,
            UnitCost: transferProd.Cost, OccurredAt: transfer.Date), ct);
        await _stock.ApplyMovementAsync(new StockMovementDraft(
            ProductId: transferProd.Id, StoreId: secondStore.Id, Quantity: transferQty,
            Type: MovementType.TransferIn, DocumentType: "transfer-in",
            DocumentId: transfer.Id, DocumentNumber: transfer.Number,
            UnitCost: transferProd.Cost, OccurredAt: transfer.Date), ct);
        _db.Transfers.Add(transfer);

        // ── 1 инвентаризация (Posted) с небольшим diff ──────────────────────
        var invProds = products.OrderBy(_ => _rng.Next()).Take(5).ToList();
        var inv = new InventoryDoc
        {
            OrganizationId = orgId,
            Number = "ИНВ-DEMO-001",
            Date = now.AddDays(-1), Status = InventoryStatus.Posted, PostedAt = now.AddDays(-1),
            StoreId = mainStore.Id, Notes = "DEMO",
        };
        int iOrder = 0;
        foreach (var p in invProds)
        {
            var book = await _db.Stocks
                .Where(s => s.StoreId == mainStore.Id && s.ProductId == p.Id)
                .Select(s => (decimal?)s.Quantity).FirstOrDefaultAsync(ct) ?? 0m;
            // Для демо: +/- 1 от книги (можно случайно)
            var diff = _rng.Next(-1, 2);
            var actual = Math.Max(0m, book + diff);
            inv.Lines.Add(new InventoryLine
            {
                OrganizationId = orgId,
                InventoryDocId = inv.Id,
                ProductId = p.Id, BookQty = book, ActualQty = actual, Diff = actual - book,
                UnitCost = p.Cost, SortOrder = iOrder++,
            });
            if (actual - book != 0m)
            {
                await _stock.ApplyMovementAsync(new StockMovementDraft(
                    ProductId: p.Id, StoreId: mainStore.Id, Quantity: actual - book,
                    Type: MovementType.InventoryAdjustment, DocumentType: "inventory",
                    DocumentId: inv.Id, DocumentNumber: inv.Number,
                    UnitCost: p.Cost, OccurredAt: inv.Date,
                    Notes: actual > book ? "surplus" : "shortage"), ct);
            }
        }
        _db.InventoryDocs.Add(inv);

        await _db.SaveChangesAsync(ct);
        await tx.CommitAsync(ct);

        return new SeedSummary(
            AlreadySeeded: false,
            Groups: groups.Count,
            Products: products.Count,
            Counterparties: counterparties.Count,
            Supplies: supplies.Count,
            Sales: 30,
            Demands: 1,
            Losses: 1,
            Transfers: 1,
            Inventories: 1,
            Stores: stores.Count + (secondStore is { } ? 1 : 0));
    }

    /// <summary>Только считает, ничего не вставляет. Используется в GET-status.</summary>
    public async Task<SeedSummary> PeekAsync(Guid orgId, CancellationToken ct)
    {
        var hasDemo = await _db.Products.IgnoreQueryFilters()
            .AnyAsync(p => p.OrganizationId == orgId && p.Article != null && p.Article.StartsWith("DEMO-"), ct);
        var counts = await CountExistingAsync(orgId, ct);
        return counts with { AlreadySeeded = hasDemo };
    }

    private async Task<SeedSummary> CountExistingAsync(Guid orgId, CancellationToken ct)
    {
        var prodCount = await _db.Products.IgnoreQueryFilters().CountAsync(p => p.OrganizationId == orgId, ct);
        var groupCount = await _db.ProductGroups.IgnoreQueryFilters().CountAsync(g => g.OrganizationId == orgId, ct);
        var cpCount = await _db.Counterparties.IgnoreQueryFilters().CountAsync(c => c.OrganizationId == orgId, ct);
        var supCount = await _db.Supplies.IgnoreQueryFilters().CountAsync(s => s.OrganizationId == orgId, ct);
        var saleCount = await _db.RetailSales.IgnoreQueryFilters().CountAsync(s => s.OrganizationId == orgId, ct);
        var dmCount = await _db.Demands.IgnoreQueryFilters().CountAsync(d => d.OrganizationId == orgId, ct);
        var lossCount = await _db.Losses.IgnoreQueryFilters().CountAsync(l => l.OrganizationId == orgId, ct);
        var trCount = await _db.Transfers.IgnoreQueryFilters().CountAsync(t => t.OrganizationId == orgId, ct);
        var invCount = await _db.InventoryDocs.IgnoreQueryFilters().CountAsync(i => i.OrganizationId == orgId, ct);
        var storeCount = await _db.Stores.IgnoreQueryFilters().CountAsync(s => s.OrganizationId == orgId, ct);
        return new SeedSummary(true,
            groupCount, prodCount, cpCount,
            supCount, saleCount, dmCount, lossCount, trCount, invCount, storeCount);
    }

    // ── helpers ─────────────────────────────────────────────────────────────

    private static string MakeEan13(long body12)
    {
        // body12 — 12 цифр; считаем чек-сумму EAN-13.
        var s = body12.ToString("D12");
        var sum = 0;
        for (int i = 0; i < 12; i++)
        {
            var d = s[i] - '0';
            sum += i % 2 == 0 ? d : d * 3;
        }
        var checksum = (10 - sum % 10) % 10;
        return s + checksum;
    }

    private static string NextBin(long seed)
    {
        // 12-значный BIN, начинается с 1234... для DEMO.
        var s = $"1234{(seed % 100000000):D8}";
        return s[..12];
    }

    private sealed record ProductTpl(string Name, string Unit, decimal RetailPrice);

    private static ProductTpl[][] BuildProductCatalog() => new[]
    {
        // 0: Молочные
        new[]
        {
            new ProductTpl("Молоко 3.2% 1л", "l", 480m),
            new ProductTpl("Молоко 1.5% 1л", "l", 460m),
            new ProductTpl("Кефир 1% 0.5л", "l", 280m),
            new ProductTpl("Йогурт натуральный 250г", "sht", 250m),
            new ProductTpl("Сметана 20% 200г", "sht", 320m),
            new ProductTpl("Сыр Голландский 1кг", "kg", 3200m),
            new ProductTpl("Творог 5% 200г", "sht", 360m),
            new ProductTpl("Масло сливочное 200г", "sht", 850m),
            new ProductTpl("Ряженка 1л", "l", 510m),
            new ProductTpl("Сливки 20% 200мл", "sht", 420m),
        },
        // 1: Хлеб
        new[]
        {
            new ProductTpl("Хлеб ржаной 600г", "sht", 220m),
            new ProductTpl("Хлеб пшеничный 500г", "sht", 200m),
            new ProductTpl("Багет французский 250г", "sht", 280m),
            new ProductTpl("Лаваш тонкий 300г", "sht", 180m),
            new ProductTpl("Хлеб бородинский 400г", "sht", 240m),
            new ProductTpl("Булочка с маком 80г", "sht", 95m),
            new ProductTpl("Слойка с творогом 100г", "sht", 180m),
            new ProductTpl("Пита 200г", "sht", 150m),
            new ProductTpl("Сухари ванильные 200г", "sht", 220m),
            new ProductTpl("Печенье овсяное 250г", "sht", 380m),
        },
        // 2: Напитки
        new[]
        {
            new ProductTpl("Вода негазированная 1.5л", "l", 280m),
            new ProductTpl("Вода газированная 1.5л", "l", 290m),
            new ProductTpl("Кола 0.5л", "l", 350m),
            new ProductTpl("Сок яблочный 1л", "l", 520m),
            new ProductTpl("Сок апельсиновый 1л", "l", 580m),
            new ProductTpl("Чай чёрный пакетированный 25шт", "sht", 480m),
            new ProductTpl("Чай зелёный 100г", "sht", 720m),
            new ProductTpl("Кофе растворимый 100г", "sht", 1850m),
            new ProductTpl("Энергетик 0.5л", "l", 580m),
            new ProductTpl("Морс клюквенный 1л", "l", 420m),
        },
        // 3: Бакалея
        new[]
        {
            new ProductTpl("Рис круглозерный 1кг", "kg", 480m),
            new ProductTpl("Гречка ядрица 800г", "sht", 520m),
            new ProductTpl("Макароны спагетти 500г", "sht", 380m),
            new ProductTpl("Сахар-песок 1кг", "kg", 420m),
            new ProductTpl("Соль поваренная 1кг", "kg", 180m),
            new ProductTpl("Мука пшеничная 2кг", "sht", 680m),
            new ProductTpl("Масло подсолнечное 1л", "l", 1280m),
            new ProductTpl("Уксус 9% 500мл", "sht", 250m),
            new ProductTpl("Перец чёрный молотый 50г", "sht", 320m),
            new ProductTpl("Лавровый лист 10г", "sht", 180m),
        },
        // 4: Снеки
        new[]
        {
            new ProductTpl("Чипсы Lay's 150г", "sht", 580m),
            new ProductTpl("Сухарики Воронцовские 60г", "sht", 180m),
            new ProductTpl("Орешки солёные 100г", "sht", 480m),
            new ProductTpl("Семечки жареные 100г", "sht", 280m),
            new ProductTpl("Шоколад молочный 90г", "sht", 580m),
            new ProductTpl("Батончик Snickers 50г", "sht", 380m),
            new ProductTpl("Конфеты ассорти 200г", "sht", 1280m),
            new ProductTpl("Печенье шоколадное 200г", "sht", 480m),
            new ProductTpl("Жевательная резинка 14г", "sht", 180m),
            new ProductTpl("Мармелад 200г", "sht", 380m),
        },
    };
}
