using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace GestionaDenuncias.Shared.Models;

public class DenunciasGestiona
{
    public int Id_RegistroDenuncia { get; set; }
    public int Id_Denuncia { get; set; }
    public DateTime Fecha { get; set; } = DateTime.MinValue;
    public string Expediente_Gestiona { get; set; } = string.Empty;
    public string CodigoExpedienteGestiona { get; set; } = string.Empty;
    public int Id_Persona_Gestiona { get; set; }
    public string Etiqueta { get; set; } = string.Empty;
    public string Estado { get; set; } = string.Empty;

    public string Tipo_Denuncia { get; set; } = string.Empty;
    public string TipoDenunciante { get; set; } = string.Empty;
    public bool EsPersonaJuridica { get; set; }
    public string Nombre { get; set; } = string.Empty;
    public string PrimerApellido { get; set; } = string.Empty;
    public string SegundoApellido { get; set; } = string.Empty;
    public string Apellidos { get; set; } = string.Empty;
    public string RazonSocial { get; set; } = string.Empty;
    public string Sexo { get; set; } = string.Empty;
    public string Dni { get; set; } = string.Empty;
    public string TipoDocumentoIdentificativo { get; set; } = string.Empty;
    public string PaisOrigen { get; set; } = string.Empty;
    public string Asunto { get; set; } = string.Empty;
    public string A_Quien_Denuncia { get; set; } = string.Empty;
    public string DenunciadoDetalle { get; set; } = string.Empty;
    public string Descripcion_Denuncia { get; set; } = string.Empty;
    public string Denunciado_Ante_Inst { get; set; } = string.Empty;
    public string OrganismoDenunciado { get; set; } = string.Empty;
    public string SolicitaProteccion { get; set; } = string.Empty;
    public string MedidasProteccionSolicitadas { get; set; } = string.Empty;
    public string Modalidad_Informacion { get; set; } = string.Empty;
    public string Lugar_Hechos { get; set; } = string.Empty;
    public DateTime Fecha_Hechos { get; set; } = DateTime.MinValue;
    public string AutorizaRemision { get; set; } = string.Empty;
    public string PreferenciaRemision { get; set; } = string.Empty;
    public string Notificacion_Preferencia { get; set; } = string.Empty;
    public string Notificacion_Electronica { get; set; } = string.Empty;
    public string SeguimientoOnline { get; set; } = string.Empty;
    public string NotificacionPostal { get; set; } = string.Empty;
    public string Correo_Electronico { get; set; } = string.Empty;
    public string Notificacion_Sms { get; set; } = string.Empty;
    public bool Condiciones { get; set; }
    public string Comments { get; set; } = string.Empty;
    public string Telefono { get; set; } = string.Empty;
    public string Direccion { get; set; } = string.Empty;
    public string DireccionTipoVia { get; set; } = string.Empty;
    public string DireccionNumero { get; set; } = string.Empty;
    public string DireccionPiso { get; set; } = string.Empty;
    public string DireccionPuerta { get; set; } = string.Empty;
    public string DireccionBloque { get; set; } = string.Empty;
    public string DireccionEscalera { get; set; } = string.Empty;
    public string DireccionExtra { get; set; } = string.Empty;
    public string Municipio { get; set; } = string.Empty;
    public string Provincia { get; set; } = string.Empty;
    public string CodigoPostal { get; set; } = string.Empty;
    public string Pais { get; set; } = string.Empty;
    public string CamposFormularioJson { get; set; } = string.Empty;
    public string TextoOriginalReport { get; set; } = string.Empty;

    public bool Confidencial { get; set; }

    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool EsActualizacion { get; set; }

    public Guid ProcedureId { get; set; } = Guid.Empty;
    public Guid GroupId { get; set; } = Guid.Empty;

    public string NombreDenuncia { get; set; } = string.Empty;
    public string EstadoDenuncia { get; set; } = string.Empty;
    public string ArchivoElegido { get; set; } = string.Empty;
    public DateTime FechaSubidaAGestiona { get; set; } = DateTime.MinValue;
    public string UltimaSubidaGestionaTipo { get; set; } = string.Empty;
    public string UltimoGrupoAsignadoGestiona { get; set; } = string.Empty;
    public string PendingUpdateSource { get; set; } = string.Empty;

    public bool EnGestiona { get; set; }
    public bool EnRechazada { get; set; }

    public string OwnerUsername { get; set; } = string.Empty;
    public bool OwnedByCurrentUser { get; set; }
    public bool RequiresOwnerConfirmation { get; set; }
    public IReadOnlyList<string> OwnerWorkGroups { get; set; } = [];

    [JsonIgnore]
    public DateOnly? KeyDate { get; set; }

    [JsonIgnore]
    public string EncryptionScheme { get; set; } = string.Empty;

    [JsonIgnore]
    public DateTime? EncryptedAtUtc { get; set; }

    [JsonIgnore]
    public string NombreResuelto => ResolveValue(Nombre, "nombre");

    [JsonIgnore]
    public string PrimerApellidoResuelto => ResolveValue(PrimerApellido, "1 apellido", "primer apellido");

    [JsonIgnore]
    public string SegundoApellidoResuelto => ResolveValue(SegundoApellido, "2 apellido", "segundo apellido");

    [JsonIgnore]
    public string ApellidosResueltos
    {
        get
        {
            if (!string.IsNullOrWhiteSpace(Apellidos))
            {
                return Apellidos.Trim();
            }

            return string.Join(
                ' ',
                new[] { PrimerApellidoResuelto, SegundoApellidoResuelto }
                    .Where(value => !string.IsNullOrWhiteSpace(value)));
        }
    }

    [JsonIgnore]
    public string RazonSocialResuelta => ResolveValue(RazonSocial, "razon social");

    [JsonIgnore]
    public string DocumentoResuelto => ResolveValue(
        Dni,
        "nif dni nie",
        "dni",
        "nif",
        "nie",
        "cif",
        "otro documento identificativo");

    [JsonIgnore]
    public bool EsAnonima
    {
        get
        {
            if (IndicaDenunciaIdentificada(Tipo_Denuncia))
            {
                return false;
            }

            if (Confidencial)
            {
                return true;
            }

            if (IndicaDenunciaAnonima(Tipo_Denuncia))
            {
                return true;
            }

            return string.IsNullOrWhiteSpace(DocumentoResuelto) &&
                   string.IsNullOrWhiteSpace(NombreResuelto) &&
                   string.IsNullOrWhiteSpace(RazonSocialResuelta);
        }
    }

    [JsonIgnore]
    public string NombreDenuncianteMostrar =>
        EsPersonaJuridica
            ? RazonSocialResuelta
            : string.Join(
                ' ',
                new[] { NombreResuelto, PrimerApellidoResuelto, SegundoApellidoResuelto }
                    .Where(value => !string.IsNullOrWhiteSpace(value)));

    [JsonIgnore]
    public string ExpedienteGestionaMostrable
    {
        get
        {
            if (!string.IsNullOrWhiteSpace(CodigoExpedienteGestiona))
            {
                return CodigoExpedienteGestiona.Trim();
            }

            if (string.IsNullOrWhiteSpace(Expediente_Gestiona))
            {
                return string.Empty;
            }

            return string.Equals(Expediente_Gestiona, "Pendiente", StringComparison.OrdinalIgnoreCase)
                ? "Pendiente"
                : "Pendiente de sincronizar";
        }
    }

    [JsonIgnore]
    public string UltimaSubidaGestionaTipoMostrable =>
        string.IsNullOrWhiteSpace(UltimaSubidaGestionaTipo)
            ? string.Empty
            : UltimaSubidaGestionaTipo.Trim();

    [JsonIgnore]
    public string UltimoGrupoAsignadoGestionaMostrable =>
        string.IsNullOrWhiteSpace(UltimoGrupoAsignadoGestiona)
            ? string.Empty
            : UltimoGrupoAsignadoGestiona.Trim();

    public IReadOnlyList<ReportFieldEntry> GetCamposFormulario()
    {
        if (string.IsNullOrWhiteSpace(CamposFormularioJson))
        {
            return [];
        }

        try
        {
            return JsonSerializer.Deserialize<List<ReportFieldEntry>>(CamposFormularioJson) ?? [];
        }
        catch
        {
            return [];
        }
    }

    public void SetCamposFormulario(IEnumerable<ReportFieldEntry> fields)
    {
        var list = fields?.ToList() ?? [];
        CamposFormularioJson = list.Count == 0
            ? string.Empty
            : JsonSerializer.Serialize(list);
    }

    public static bool IndicaDenunciaAnonima(string? tipoDenuncia)
    {
        var normalized = NormalizeLabel(tipoDenuncia);
        if (string.IsNullOrWhiteSpace(normalized))
        {
            return false;
        }

        if (IndicaDenunciaIdentificada(tipoDenuncia))
        {
            return false;
        }

        return normalized == "anonima" ||
               normalized == "anonimo" ||
               normalized.Contains("denuncia anonima", StringComparison.Ordinal) ||
               normalized.Contains("anonima", StringComparison.Ordinal) ||
               normalized.Contains("anonimo", StringComparison.Ordinal);
    }

    public static bool IndicaDenunciaIdentificada(string? tipoDenuncia)
    {
        var normalized = NormalizeLabel(tipoDenuncia);
        if (string.IsNullOrWhiteSpace(normalized))
        {
            return false;
        }

        return normalized.Contains("no anonima", StringComparison.Ordinal) ||
               normalized.Contains("no anonimo", StringComparison.Ordinal) ||
               normalized.Contains("deseo identificarme", StringComparison.Ordinal) ||
               normalized.Contains("quiero identificarme", StringComparison.Ordinal) ||
               normalized.Contains("identificarme", StringComparison.Ordinal);
    }

    private string ResolveValue(string currentValue, params string[] fallbackLabels)
    {
        if (!string.IsNullOrWhiteSpace(currentValue))
        {
            return currentValue.Trim();
        }

        var labels = fallbackLabels
            .Select(NormalizeLabel)
            .ToHashSet(StringComparer.Ordinal);

        foreach (var field in GetCamposFormulario())
        {
            if (labels.Contains(NormalizeLabel(field.Label)) &&
                !string.IsNullOrWhiteSpace(field.Value))
            {
                return field.Value.Trim();
            }
        }

        return string.Empty;
    }

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

        var normalized = value.Normalize(NormalizationForm.FormD);
        var builder = new StringBuilder(normalized.Length);

        foreach (var ch in normalized)
        {
            if (CharUnicodeInfo.GetUnicodeCategory(ch) != UnicodeCategory.NonSpacingMark)
            {
                if (ch is 'º' or 'ª')
                {
                    continue;
                }

                builder.Append(char.IsLetterOrDigit(ch) ? char.ToLowerInvariant(ch) : ' ');
            }
        }

        return string.Join(
            ' ',
            builder
                .ToString()
                .Normalize(NormalizationForm.FormC)
                .Split(' ', StringSplitOptions.RemoveEmptyEntries));
    }
}
