using System.Globalization; using System.Text; using line_gestao_api.Dtos; using line_gestao_api.Models; using Microsoft.EntityFrameworkCore; namespace line_gestao_api.Services { public sealed record OperadoraContaContext(string Operadora, string Empresa, string? VivoEmpresaGrupo = null); public static class OperadoraContaResolver { private const string OperadoraVivo = "VIVO"; private const string OperadoraClaro = "CLARO"; private const string OperadoraTim = "TIM"; private const string OperadoraOutra = "OUTRA"; private const string EmpresaVivoMacrophony = "VIVO MACROPHONY"; private const string EmpresaVivoLineMovel = "VIVO LINE MÓVEL"; private const string EmpresaClaroLineMovel = "CLARO LINE MÓVEL"; private const string EmpresaTimLineMovel = "TIM LINE MÓVEL"; private static readonly IReadOnlyList CompanyRules = new List { new() { Empresa = EmpresaClaroLineMovel, Contas = new List { "172593311", "172593840", "187890982" } }, new() { Empresa = EmpresaVivoMacrophony, Contas = new List { "0430237019", "0437488125", "0449508564", "0454371844", "455371844", "460161507" } }, new() { Empresa = EmpresaVivoLineMovel, Contas = new List { "0435288088" } }, new() { Empresa = EmpresaTimLineMovel, Contas = new List { "TIM" } } }; private static readonly string[] VivoContaFilters = BuildContaFilterSet(EmpresaVivoMacrophony, EmpresaVivoLineMovel); private static readonly string[] ClaroContaFilters = BuildContaFilterSet(EmpresaClaroLineMovel); private static readonly string[] TimContaFilters = BuildContaFilterSet(EmpresaTimLineMovel); private static readonly Dictionary EmpresaByConta = BuildEmpresaByConta(); public static List GetAccountCompanies() { return CompanyRules .Select(x => new AccountCompanyDto { Empresa = x.Empresa, Contas = x.Contas.ToList() }) .ToList(); } public static List GetAccountsByEmpresa(string? empresa) { if (string.IsNullOrWhiteSpace(empresa)) return new List(); var target = NormalizeToken(empresa); if (string.IsNullOrWhiteSpace(target)) return new List(); return CompanyRules .FirstOrDefault(x => NormalizeToken(x.Empresa) == target) ?.Contas ?.ToList() ?? new List(); } public static OperadoraContaContext Resolve(string? conta) { var contaRaw = (conta ?? string.Empty).Trim(); if (string.IsNullOrWhiteSpace(contaRaw)) { return new OperadoraContaContext(OperadoraOutra, string.Empty, null); } var normalizedConta = NormalizeConta(contaRaw); if (!string.IsNullOrWhiteSpace(normalizedConta) && EmpresaByConta.TryGetValue(normalizedConta, out var empresaDeterministica)) { return BuildContextByEmpresa(empresaDeterministica); } var token = NormalizeToken(contaRaw); if (token.Contains("TIM", StringComparison.Ordinal)) { return BuildContextByEmpresa(EmpresaTimLineMovel); } if (token.Contains("CLARO", StringComparison.Ordinal)) { return BuildContextByEmpresa(EmpresaClaroLineMovel); } if (token.Contains("MACROPHONY", StringComparison.Ordinal)) { return BuildContextByEmpresa(EmpresaVivoMacrophony); } if (token.Contains("VIVO", StringComparison.Ordinal)) { return BuildContextByEmpresa(EmpresaVivoLineMovel); } return new OperadoraContaContext(OperadoraOutra, string.Empty, null); } public static IQueryable ApplyOperadoraFilter(IQueryable query, string? operadora) { var token = NormalizeToken(operadora); if (string.IsNullOrWhiteSpace(token) || token == "TODOS" || token == "ALL") { return query; } return token switch { OperadoraVivo => query.Where(x => (x.Conta != null && VivoContaFilters.Contains(x.Conta.Trim())) || EF.Functions.ILike((x.Conta ?? string.Empty).Trim(), "%VIVO%") || EF.Functions.ILike((x.Conta ?? string.Empty).Trim(), "%MACROPHONY%")), OperadoraClaro => query.Where(x => (x.Conta != null && ClaroContaFilters.Contains(x.Conta.Trim())) || EF.Functions.ILike((x.Conta ?? string.Empty).Trim(), "%CLARO%")), OperadoraTim => query.Where(x => (x.Conta != null && TimContaFilters.Contains(x.Conta.Trim())) || EF.Functions.ILike((x.Conta ?? string.Empty).Trim(), "%TIM%")), _ => query }; } public static string NormalizeConta(string? conta) { var raw = (conta ?? string.Empty).Trim(); if (string.IsNullOrWhiteSpace(raw)) return string.Empty; if (raw.All(char.IsDigit)) { var noLeadingZero = raw.TrimStart('0'); return string.IsNullOrWhiteSpace(noLeadingZero) ? "0" : noLeadingZero; } return RemoveDiacritics(raw).ToUpperInvariant(); } private static OperadoraContaContext BuildContextByEmpresa(string empresa) { var token = NormalizeToken(empresa); var operadora = token.Contains("CLARO", StringComparison.Ordinal) ? OperadoraClaro : token.Contains("TIM", StringComparison.Ordinal) ? OperadoraTim : token.Contains("VIVO", StringComparison.Ordinal) || token.Contains("MACROPHONY", StringComparison.Ordinal) ? OperadoraVivo : OperadoraOutra; var vivoGrupo = operadora == OperadoraVivo ? token.Contains("MACROPHONY", StringComparison.Ordinal) ? "MACROPHONY" : token.Contains("LINEMOVEL", StringComparison.Ordinal) ? "LINE MOVEL" : null : null; return new OperadoraContaContext(operadora, empresa, vivoGrupo); } private static Dictionary BuildEmpresaByConta() { var map = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (var group in CompanyRules) { foreach (var conta in group.Contas ?? new List()) { var normalized = NormalizeConta(conta); if (string.IsNullOrWhiteSpace(normalized)) continue; map[normalized] = group.Empresa; } } return map; } private static string[] BuildContaFilterSet(params string[] empresas) { var empresaTokens = new HashSet(empresas.Select(NormalizeToken), StringComparer.OrdinalIgnoreCase); var set = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (var group in CompanyRules) { if (!empresaTokens.Contains(NormalizeToken(group.Empresa))) continue; foreach (var conta in group.Contas ?? new List()) { var trimmed = (conta ?? string.Empty).Trim(); if (string.IsNullOrWhiteSpace(trimmed)) continue; set.Add(trimmed); if (trimmed.All(char.IsDigit)) { var noLeading = trimmed.TrimStart('0'); if (!string.IsNullOrWhiteSpace(noLeading)) { set.Add(noLeading); } } } } return set.ToArray(); } private static string NormalizeToken(string? value) { if (string.IsNullOrWhiteSpace(value)) return string.Empty; var raw = RemoveDiacritics(value); var sb = new StringBuilder(raw.Length); foreach (var ch in raw) { if (char.IsLetterOrDigit(ch)) sb.Append(char.ToUpperInvariant(ch)); } return sb.ToString(); } private static string RemoveDiacritics(string value) { if (string.IsNullOrWhiteSpace(value)) return string.Empty; var normalized = value.Normalize(NormalizationForm.FormD); var sb = new StringBuilder(normalized.Length); foreach (var c in normalized) { var category = CharUnicodeInfo.GetUnicodeCategory(c); if (category != UnicodeCategory.NonSpacingMark) { sb.Append(c); } } return sb.ToString().Normalize(NormalizationForm.FormC); } } }