using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.Core.Repositories.Interfaces.Unit;
using PARR.Core.Services.Shortcodes.Enums;
using PARR.Core.Services.Shortcodes.Models;
using System.Text.RegularExpressions;

namespace PARR.Core.Services.Shortcodes.Handlers;

internal class RelationshipUnitShortcodeHandler : IShortcodeHandler
{
    private readonly IUnitInValueRepository unitInValueRepo;
    private readonly ILogger<RelationshipUnitShortcodeHandler> logger;

    public int Order => 50;

    private static readonly Regex _pattern = new(@"%СВЯЗЬ:([^%]+)%", RegexOptions.Compiled | RegexOptions.IgnoreCase);
    public Regex Pattern => _pattern;

    public ShortcodeDataRequirementsEnum Requirements => ShortcodeDataRequirementsEnum.UnitsInTemplate;

    public RelationshipUnitShortcodeHandler(
        IUnitInValueRepository unitInValueRepo,
        ILogger<RelationshipUnitShortcodeHandler> logger)
    {
        this.unitInValueRepo = unitInValueRepo;
        this.logger = logger;
    }

    public async Task<string> ResolveAsync(string input, TemplateForShortcode template, string caller, CancellationToken ct = default)
    {
        var matches = Pattern.Matches(input);
        if (matches.Count == 0) return input;

        var uniqueFields = matches.Cast<Match>()
            .Select(m => m.Value.Trim('%').Split(':', 2)[1].Trim())
            .Distinct(StringComparer.OrdinalIgnoreCase)
            .ToList();

        var resolved = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        foreach (var field in uniqueFields)
        {
            resolved[$"%СВЯЗЬ:{field}%"] = await GetRelValueAsync(template, field, caller, ct);
        }

        var result = input;
        foreach (Match m in matches)
        {
            if (resolved.TryGetValue(m.Value, out var val))
                result = result.Replace(m.Value, val, StringComparison.OrdinalIgnoreCase);
        }
        return result;
    }

    private async Task<string> GetRelValueAsync(TemplateForShortcode template, string fieldName, string caller, CancellationToken ct)
    {
        if (template.UnitsInTemplate.Count == 0)
        {
            logger.LogDebug("[{Caller}] %СВЯЗЬ:{Field}% пропущен: UnitsInTemplate пуст.", caller, fieldName);
            return string.Empty;
        }

        var unitIds = template.UnitsInTemplate.Select(u => u.UnitId).Distinct().ToList();

        var allValues = await unitInValueRepo.Get()
            .AsNoTracking()
            .Include(uv => uv.Field)
            .Include(uv => uv.Value)
            .Where(uv => unitIds.Contains(uv.UnitId) &&
                         uv.Field!.AihitName == fieldName &&
                         uv.Value != null &&
                         !string.IsNullOrEmpty(uv.Value.Value))
            .Select(uv => uv.Value!.Value)
            .ToListAsync(ct);

        if (allValues.Count == 0) return string.Empty;

        var mostPopular = allValues
            .GroupBy(v => v, StringComparer.OrdinalIgnoreCase)
            .Select(g => new { Value = g.Key, Count = g.Count() })
            .OrderByDescending(x => x.Count)
            .ThenBy(x => x.Value, StringComparer.OrdinalIgnoreCase)
            .FirstOrDefault();

        return mostPopular?.Value ?? string.Empty;
    }
}