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

namespace Meezi.API.Services;

public record DemoSeedResult(
    int CategoriesAdded,
    int ItemsAdded,
    int TablesAdded,
    int IngredientsAdded,
    bool TaxCreated);

public interface IDemoSeedService
{
    Task<DemoSeedResult> SeedAsync(string cafeId, CancellationToken ct = default);
}

public class DemoSeedService : IDemoSeedService
{
    private readonly AppDbContext _db;
    private readonly ILogger<DemoSeedService> _logger;

    public DemoSeedService(AppDbContext db, ILogger<DemoSeedService> logger)
    {
        _db = db;
        _logger = logger;
    }

    public async Task<DemoSeedResult> SeedAsync(string cafeId, CancellationToken ct = default)
    {
        // 1. Ensure 9% default tax
        var taxId = $"{cafeId}_demo_tax";
        var taxCreated = false;
        if (!await _db.Taxes.AnyAsync(t => t.CafeId == cafeId && t.IsDefault, ct))
        {
            _db.Taxes.Add(new Tax
            {
                Id = taxId,
                CafeId = cafeId,
                Name = "مالیات ارزش افزوده",
                Rate = 9,
                IsDefault = true,
                IsRequired = true,
                IsCompound = false
            });
            await _db.SaveChangesAsync(ct);
            taxCreated = true;
        }
        else
        {
            taxId = await _db.Taxes
                .Where(t => t.CafeId == cafeId && t.IsDefault)
                .Select(t => t.Id)
                .FirstAsync(ct);
        }

        // 2. Seed menu (categories + items) using café-agnostic seeder
        var beforeCats = await _db.MenuCategories.CountAsync(c => c.CafeId == cafeId, ct);
        var beforeItems = await _db.MenuItems.CountAsync(i => i.CafeId == cafeId, ct);
        await DemoMenuSeeder.EnsureMenuAsync(_db, cafeId, taxId, _logger);
        var afterCats = await _db.MenuCategories.CountAsync(c => c.CafeId == cafeId, ct);
        var afterItems = await _db.MenuItems.CountAsync(i => i.CafeId == cafeId, ct);

        // 3. Seed ingredients if warehouse is empty
        var ingredientsAdded = 0;
        if (!await _db.Ingredients.AnyAsync(i => i.CafeId == cafeId, ct))
        {
            var demoIngredients = BuildDemoIngredients(cafeId);
            _db.Ingredients.AddRange(demoIngredients);
            await _db.SaveChangesAsync(ct);
            ingredientsAdded = demoIngredients.Count;
        }

        // 4. Seed 10 tables if no tables exist for this café's first active branch
        var tablesAdded = 0;
        if (!await _db.Tables.AnyAsync(t => t.CafeId == cafeId, ct))
        {
            var branchId = await _db.Branches
                .Where(b => b.CafeId == cafeId && b.IsActive && b.DeletedAt == null)
                .OrderBy(b => b.Id)
                .Select(b => b.Id)
                .FirstOrDefaultAsync(ct);

            if (branchId is not null)
            {
                var tables = BuildDemoTables(cafeId, branchId);
                _db.Tables.AddRange(tables);
                await _db.SaveChangesAsync(ct);
                tablesAdded = tables.Count;
            }
        }

        _logger.LogInformation(
            "Demo seed complete for cafe {CafeId}: +{Cats} cats, +{Items} items, +{Tables} tables, +{Ing} ingredients, tax={TaxCreated}",
            cafeId, afterCats - beforeCats, afterItems - beforeItems, tablesAdded, ingredientsAdded, taxCreated);

        return new DemoSeedResult(
            CategoriesAdded: afterCats - beforeCats,
            ItemsAdded: afterItems - beforeItems,
            TablesAdded: tablesAdded,
            IngredientsAdded: ingredientsAdded,
            TaxCreated: taxCreated);
    }

    private static List<Ingredient> BuildDemoIngredients(string cafeId) =>
    [
        Ingredient(cafeId, "قهوه اسپرسو", "گرم", 2000, 500, 80, 2000),
        Ingredient(cafeId, "شیر", "میلی‌لیتر", 10000, 2000, 15, 10000),
        Ingredient(cafeId, "شکر", "گرم", 5000, 1000, 5, 5000),
        Ingredient(cafeId, "وانیل", "میلی‌لیتر", 500, 100, 50, 500),
        Ingredient(cafeId, "شکلات تلخ", "گرم", 1000, 200, 120, 1000),
        Ingredient(cafeId, "خامه", "میلی‌لیتر", 2000, 500, 30, 2000),
        Ingredient(cafeId, "دارچین", "گرم", 300, 50, 40, 300),
        Ingredient(cafeId, "چای سیاه", "گرم", 1000, 200, 60, 1000),
        Ingredient(cafeId, "آب معدنی", "میلی‌لیتر", 20000, 5000, 3, 20000),
        Ingredient(cafeId, "نان تست", "عدد", 100, 20, 8000, 100),
        Ingredient(cafeId, "تخم‌مرغ", "عدد", 60, 12, 6000, 60),
        Ingredient(cafeId, "کره", "گرم", 500, 100, 80, 500),
        Ingredient(cafeId, "پنیر", "گرم", 1000, 200, 90, 1000),
        Ingredient(cafeId, "اسپاتولا یخ", "عدد", 200, 50, 2000, 200),
        Ingredient(cafeId, "سس کارامل", "میلی‌لیتر", 1000, 200, 60, 1000),
    ];

    private static Ingredient Ingredient(
        string cafeId, string name, string unit,
        decimal qty, decimal reorder, decimal cost, decimal par) =>
        new()
        {
            Id = $"{cafeId}_ing_{Guid.NewGuid():N}"[..36],
            CafeId = cafeId,
            Name = name,
            Unit = unit,
            QuantityOnHand = qty,
            ReorderLevel = reorder,
            UnitCost = cost,
            ParLevel = par,
            LowStockWarningPercent = 20m
        };

    private static List<Table> BuildDemoTables(string cafeId, string branchId)
    {
        var tables = new List<Table>();
        // Floor 1: tables 1-4
        for (var i = 1; i <= 4; i++)
            tables.Add(Table(cafeId, branchId, i.ToString(), 4, "طبقه اول", i));
        // Floor 2: tables 5-8
        for (var i = 5; i <= 8; i++)
            tables.Add(Table(cafeId, branchId, i.ToString(), 4, "طبقه دوم", i));
        // VIP: tables 9-10
        for (var i = 9; i <= 10; i++)
            tables.Add(Table(cafeId, branchId, i.ToString(), 6, "VIP", i));
        return tables;
    }

    private static Table Table(
        string cafeId, string branchId, string number, int capacity, string floor, int sortOrder) =>
        new()
        {
            Id = $"{cafeId}_tbl_{Guid.NewGuid():N}"[..36],
            CafeId = cafeId,
            BranchId = branchId,
            Number = number,
            Capacity = capacity,
            Floor = floor,
            SortOrder = sortOrder,
            QrCode = Guid.NewGuid().ToString("N"),
            IsActive = true,
            IsCleaning = false
        };
}
