using Meezi.Core.Branding;
using Meezi.Core.Entities;
using Meezi.Core.Enums;
using Meezi.Infrastructure.Branding;
using Meezi.Infrastructure.Discover;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace Meezi.Infrastructure.Data;

/// <summary>Seeds 30 Persian showcase cafés for public discover (development only).</summary>
public static class DiscoverShowcaseSeeder
{
    private static readonly string[] ReviewAuthors = ["سارا", "علی", "مینا", "رضا", "نازنین"];
    private static readonly string[] ReviewComments =
    [
        "فضا و نوشیدنی عالی بود.",
        "سرویس سریع، پیشنهاد می‌کنم.",
        "مناسب قرار و کار.",
        "قیمت مناسب برای کیفیت.",
        "دسر و قهوه خوشمزه بود.",
    ];

    public static async Task SeedAsync(AppDbContext db, ILogger logger)
    {
        var addedCafes = 0;
        foreach (var spec in DiscoverShowcaseCatalog.Cafes)
        {
            var cafe = await db.Cafes.FirstOrDefaultAsync(c => c.Id == spec.Id);
            if (cafe is null)
            {
                cafe = new Cafe
                {
                    Id = spec.Id,
                    Name = spec.Name,
                    NameEn = spec.Slug.Replace('-', ' '),
                    Slug = spec.Slug,
                    City = spec.City,
                    Address = spec.Address,
                    Description = spec.Description,
                    PlanTier = spec.PlanTier,
                    PreferredLanguage = "fa",
                    IsVerified = true,
                    DiscoverProfileJson = CafeDiscoverProfileSerializer.Serialize(spec.Profile),
                    DiscoverBadgesJson = DiscoverBadgesSerializer.Serialize(spec.Badges),
                    ThemeJson = CafeThemeSerializer.Serialize(new CafeTheme
                    {
                        PaletteId = CafeThemeDefaults.PaletteMeeziGreen,
                        PanelStyle = CafeThemeDefaults.PanelModern,
                        MenuStyle = CafeThemeDefaults.MenuCards,
                        Density = CafeThemeDefaults.DensityComfortable,
                        Radius = CafeThemeDefaults.RadiusMd
                    })
                };
                db.Cafes.Add(cafe);

                var branchId = BranchId(spec.Id);
                db.Branches.Add(new Branch
                {
                    Id = branchId,
                    CafeId = spec.Id,
                    Name = "شعبه اصلی",
                    City = spec.City,
                    Address = spec.Address,
                    Phone = "02100000000",
                    IsActive = true,
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                });

                db.Employees.Add(new Employee
                {
                    Id = OwnerId(spec.Id),
                    CafeId = spec.Id,
                    BranchId = branchId,
                    Name = $"مدیر {spec.Name}",
                    Phone = spec.OwnerPhone,
                    Role = EmployeeRole.Owner,
                    BaseSalary = 0
                });

                await db.SaveChangesAsync();
                addedCafes++;
            }
            else
            {
                var changed = false;
                if (string.IsNullOrEmpty(cafe.DiscoverProfileJson))
                {
                    cafe.DiscoverProfileJson = CafeDiscoverProfileSerializer.Serialize(spec.Profile);
                    changed = true;
                }
                if (string.IsNullOrEmpty(cafe.DiscoverBadgesJson) && spec.Badges is { Count: > 0 })
                {
                    cafe.DiscoverBadgesJson = DiscoverBadgesSerializer.Serialize(spec.Badges);
                    changed = true;
                }
                if (!cafe.IsVerified)
                {
                    cafe.IsVerified = true;
                    changed = true;
                }
                if (changed)
                    await db.SaveChangesAsync();
            }

            await EnsureShowcaseMenuAsync(db, spec, logger);
            await EnsureShowcaseReviewsAsync(db, spec.Id, logger);
        }

        if (addedCafes > 0)
            logger.LogInformation("Discover showcase seed: {Count} new cafés", addedCafes);
    }

    private static string BranchId(string cafeId) => $"branch_{cafeId}_main";
    private static string OwnerId(string cafeId) => $"emp_{cafeId}_owner";

    private static async Task EnsureShowcaseMenuAsync(
        AppDbContext db,
        DiscoverShowcaseCatalog.ShowcaseCafe spec,
        ILogger logger)
    {
        var taxId = $"tax_{spec.Id}";
        if (!await db.Taxes.AnyAsync(t => t.Id == taxId))
        {
            db.Taxes.Add(new Tax
            {
                Id = taxId,
                CafeId = spec.Id,
                Name = "مالیات",
                Rate = 9,
                IsDefault = true,
                IsRequired = true,
                IsCompound = false
            });
            await db.SaveChangesAsync();
        }

        var templateIndex = spec.MenuTemplateIndex % DiscoverShowcaseMenus.Templates.Count;
        var template = DiscoverShowcaseMenus.Templates[templateIndex];

        var existingCats = await db.MenuCategories
            .Where(c => c.CafeId == spec.Id)
            .Select(c => c.Id)
            .ToListAsync();

        var catsAdded = 0;
        foreach (var cat in template.Categories)
        {
            var catId = Prefixed(spec.Id, cat.Id);
            if (existingCats.Contains(catId))
                continue;

            db.MenuCategories.Add(new MenuCategory
            {
                Id = catId,
                CafeId = spec.Id,
                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
            });
            catsAdded++;
        }

        if (catsAdded > 0)
            await db.SaveChangesAsync();

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

        var itemsAdded = 0;
        foreach (var item in template.Items)
        {
            var itemId = Prefixed(spec.Id, item.Id);
            if (existingItems.Contains(itemId))
                continue;

            var catId = Prefixed(spec.Id, item.CategoryId);
            db.MenuItems.Add(new MenuItem
            {
                Id = itemId,
                CafeId = spec.Id,
                CategoryId = catId,
                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 (itemsAdded > 0)
        {
            await db.SaveChangesAsync();
            logger.LogInformation(
                "Showcase menu: cafe {Slug} +{Cats} cats +{Items} items",
                spec.Slug,
                catsAdded,
                itemsAdded);
        }
    }

    private static async Task EnsureShowcaseReviewsAsync(AppDbContext db, string cafeId, ILogger logger)
    {
        if (await db.CafeReviews.CountAsync(r => r.CafeId == cafeId) >= 2)
            return;

        var rng = new Random(cafeId.GetHashCode(StringComparison.Ordinal));
        var count = 2 - await db.CafeReviews.CountAsync(r => r.CafeId == cafeId);
        for (var i = 0; i < count; i++)
        {
            db.CafeReviews.Add(new CafeReview
            {
                CafeId = cafeId,
                AuthorName = ReviewAuthors[rng.Next(ReviewAuthors.Length)],
                Rating = rng.Next(4, 6),
                Comment = ReviewComments[rng.Next(ReviewComments.Length)],
                CreatedAt = DateTime.UtcNow.AddDays(-rng.Next(1, 30))
            });
        }

        await db.SaveChangesAsync();
        logger.LogDebug("Showcase reviews seeded for {CafeId}", cafeId);
    }

    private static string Prefixed(string cafeId, string seedId) => $"{cafeId}_{seedId}";
}
