using PowderCoating.Core.Entities;

namespace PowderCoating.Application.Services;

public enum InventoryDuplicateMatchType
{
    Sku,
    ManufacturerPartNumber,
    ManufacturerColor
}

public sealed record InventoryDuplicateMatch(
    InventoryItem Item,
    InventoryDuplicateMatchType MatchType);

/// <summary>
/// Shared inventory duplicate rules used by manual creation and powder-label scanning.
/// Callers are responsible for supplying inventory already restricted to the current tenant.
/// </summary>
public static class InventoryDuplicateMatcher
{
    public static InventoryDuplicateMatch? Find(
        IEnumerable<InventoryItem> inventoryItems,
        int companyId,
        string? sku,
        string? manufacturer,
        string? manufacturerPartNumber,
        string? colorName,
        bool isCoating,
        int? excludeId = null)
    {
        var candidates = inventoryItems
            .Where(i => i.CompanyId == companyId && i.Id != excludeId)
            .ToList();

        var normalizedSku = Normalize(sku);
        if (normalizedSku.Length > 0)
        {
            var skuMatch = candidates.FirstOrDefault(i => Normalize(i.SKU) == normalizedSku);
            if (skuMatch != null)
                return new InventoryDuplicateMatch(skuMatch, InventoryDuplicateMatchType.Sku);
        }

        if (!isCoating)
            return null;

        var coatingCandidates = candidates
            .Where(i => i.InventoryCategory?.IsCoating == true)
            .ToList();

        var normalizedManufacturer = Normalize(manufacturer);
        var normalizedPartNumber = Normalize(manufacturerPartNumber);
        if (normalizedPartNumber.Length > 0)
        {
            var partNumberMatch = coatingCandidates.FirstOrDefault(i =>
                Normalize(i.ManufacturerPartNumber) == normalizedPartNumber &&
                (normalizedManufacturer.Length == 0 ||
                 Normalize(i.Manufacturer) == normalizedManufacturer));

            if (partNumberMatch != null)
                return new InventoryDuplicateMatch(
                    partNumberMatch,
                    InventoryDuplicateMatchType.ManufacturerPartNumber);
        }

        var normalizedColorName = Normalize(colorName);
        if (normalizedManufacturer.Length == 0 || normalizedColorName.Length == 0)
            return null;

        var manufacturerColorMatch = coatingCandidates.FirstOrDefault(i =>
            Normalize(i.Manufacturer) == normalizedManufacturer &&
            Normalize(i.ColorName ?? i.Name) == normalizedColorName);

        return manufacturerColorMatch == null
            ? null
            : new InventoryDuplicateMatch(
                manufacturerColorMatch,
                InventoryDuplicateMatchType.ManufacturerColor);
    }

    private static string Normalize(string? value)
    {
        if (string.IsNullOrWhiteSpace(value))
            return string.Empty;

        return string.Join(
                ' ',
                value.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries))
            .ToUpperInvariant();
    }
}
