using Meezi.Core.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace Meezi.Infrastructure.Data;

public static class DemoMenuSeeder
{
    public static async Task EnsureMenuAsync(AppDbContext db, string cafeId, string taxId, ILogger logger)
    {
        if (!await db.Taxes.AnyAsync(t => t.Id == taxId && t.CafeId == cafeId))
        {
            db.Taxes.Add(new Tax
            {
                Id = taxId,
                CafeId = cafeId,
                Name = "مالیات",
                Rate = 9,
                IsDefault = true,
                IsRequired = true,
                IsCompound = false
            });
        }

        var existingCategoryIds = await db.MenuCategories
            .Where(c => c.CafeId == cafeId)
            .ToDictionaryAsync(c => c.Id, StringComparer.Ordinal);

        var categoriesAdded = 0;
        foreach (var cat in DemoMenuCatalog.Categories)
        {
            if (existingCategoryIds.TryGetValue(cat.Id, out var row))
            {
                if (string.IsNullOrWhiteSpace(row.Icon) && !string.IsNullOrWhiteSpace(cat.Icon))
                    row.Icon = cat.Icon;
                if (string.IsNullOrWhiteSpace(row.IconPresetId) && !string.IsNullOrWhiteSpace(cat.IconPresetId))
                    row.IconPresetId = cat.IconPresetId;
                if (string.IsNullOrWhiteSpace(row.IconStyle) && !string.IsNullOrWhiteSpace(cat.IconStyle))
                    row.IconStyle = cat.IconStyle;
                if (string.IsNullOrWhiteSpace(row.NameEn) && !string.IsNullOrWhiteSpace(cat.NameEn))
                    row.NameEn = cat.NameEn;
                if (string.IsNullOrWhiteSpace(row.NameAr) && cat.NameAr is not null)
                    row.NameAr = cat.NameAr;
                continue;
            }

            db.MenuCategories.Add(new MenuCategory
            {
                Id = cat.Id,
                CafeId = cafeId,
                Name = cat.Name,
                NameEn = cat.NameEn,
                NameAr = cat.NameAr,
                Icon = cat.Icon,
                IconPresetId = cat.IconPresetId,
                IconStyle = cat.IconStyle,
                SortOrder = cat.SortOrder,
                TaxId = taxId,
                IsActive = true
            });
            categoriesAdded++;
        }

        var existingItemIds = await db.MenuItems
            .Where(i => i.CafeId == cafeId)
            .Select(i => i.Id)
            .ToListAsync();

        var itemsAdded = 0;
        foreach (var item in DemoMenuCatalog.Items)
        {
            if (existingItemIds.Contains(item.Id))
                continue;

            db.MenuItems.Add(new MenuItem
            {
                Id = item.Id,
                CafeId = cafeId,
                CategoryId = item.CategoryId,
                Name = item.Name,
                NameEn = item.NameEn,
                NameAr = item.NameAr,
                Description = item.Description,
                Price = item.PriceToman,
                DiscountPercent = item.DiscountPercent,
                ImageUrl = DemoMenuCatalog.ResolveItemImageUrl(item),
                IsAvailable = true
            });
            itemsAdded++;
        }

        if (categoriesAdded > 0 || itemsAdded > 0)
            await db.SaveChangesAsync();

        if (categoriesAdded > 0 || itemsAdded > 0)
        {
            logger.LogInformation(
                "Demo menu seed: +{Categories} categories, +{Items} items (catalog total {Total}) for cafe {CafeId}",
                categoriesAdded,
                itemsAdded,
                DemoMenuCatalog.Items.Count,
                cafeId);
        }

        await EnsureMenuImagesAsync(db, cafeId, logger);
        await EnsureMenuTranslationsAsync(db, cafeId, logger);
    }

    /// <summary>Upserts ImageUrl from catalog/manifest/Food-101 fallbacks.</summary>
    public static async Task EnsureMenuImagesAsync(AppDbContext db, string cafeId, ILogger logger)
    {
        var catalogById = DemoMenuCatalog.Items.ToDictionary(i => i.Id, StringComparer.Ordinal);
        var items = await db.MenuItems
            .Include(i => i.Category)
            .Where(i => i.CafeId == cafeId)
            .ToListAsync();

        var updated = 0;
        foreach (var row in items)
        {
            var resolved = catalogById.TryGetValue(row.Id, out var seed)
                ? DemoMenuCatalog.ResolveItemImageUrl(seed)
                : MenuItemImageDefaults.ResolveImageUrl(row.Id, row.CategoryId, row.Category?.Name);

            if (string.IsNullOrWhiteSpace(resolved)) continue;

            var inCatalog = catalogById.ContainsKey(row.Id);
            var shouldUpdate = MenuItemImageDefaults.NeedsImageRepair(row.ImageUrl) || inCatalog;
            if (!shouldUpdate || string.Equals(row.ImageUrl, resolved, StringComparison.Ordinal))
                continue;

            row.ImageUrl = resolved;
            updated++;
        }

        if (updated > 0)
        {
            await db.SaveChangesAsync();
            logger.LogInformation("Menu image upsert: {Count} items updated for cafe {CafeId}", updated, cafeId);
        }
    }

    /// <summary>Upserts NameEn/NameAr from catalog for demo menu rows.</summary>
    public static async Task EnsureMenuTranslationsAsync(AppDbContext db, string cafeId, ILogger logger)
    {
        var catalogItems = DemoMenuCatalog.Items.ToDictionary(i => i.Id, StringComparer.Ordinal);
        var catalogCats = DemoMenuCatalog.Categories.ToDictionary(c => c.Id, StringComparer.Ordinal);

        var items = await db.MenuItems.Where(i => i.CafeId == cafeId && catalogItems.Keys.Contains(i.Id)).ToListAsync();
        var itemUpdated = 0;
        foreach (var row in items)
        {
            if (!catalogItems.TryGetValue(row.Id, out var seed)) continue;
            var changed = false;
            if (string.IsNullOrWhiteSpace(row.NameEn) && !string.IsNullOrWhiteSpace(seed.NameEn))
            {
                row.NameEn = seed.NameEn;
                changed = true;
            }
            if (string.IsNullOrWhiteSpace(row.NameAr) && seed.NameAr is not null)
            {
                row.NameAr = seed.NameAr;
                changed = true;
            }
            if (changed) itemUpdated++;
        }

        var categories = await db.MenuCategories.Where(c => c.CafeId == cafeId && catalogCats.Keys.Contains(c.Id)).ToListAsync();
        var catUpdated = 0;
        foreach (var row in categories)
        {
            if (!catalogCats.TryGetValue(row.Id, out var seed)) continue;
            var changed = false;
            if (string.IsNullOrWhiteSpace(row.NameEn) && !string.IsNullOrWhiteSpace(seed.NameEn))
            {
                row.NameEn = seed.NameEn;
                changed = true;
            }
            if (string.IsNullOrWhiteSpace(row.NameAr) && seed.NameAr is not null)
            {
                row.NameAr = seed.NameAr;
                changed = true;
            }
            if (string.IsNullOrWhiteSpace(row.Icon) && !string.IsNullOrWhiteSpace(seed.Icon))
            {
                row.Icon = seed.Icon;
                changed = true;
            }
            if (changed) catUpdated++;
        }

        if (itemUpdated > 0 || catUpdated > 0)
        {
            await db.SaveChangesAsync();
            logger.LogInformation(
                "Menu translation upsert: {Items} items, {Cats} categories for cafe {CafeId}",
                itemUpdated,
                catUpdated,
                cafeId);
        }
    }
}
