namespace SIGCM2.Domain.Entities;

public sealed class Usuario
{
    public int Id { get; }
    public string Username { get; }
    public string PasswordHash { get; }
    public string Nombre { get; }
    public string Apellido { get; }
    public string? Email { get; }
    public string Rol { get; }
    public string PermisosJson { get; }
    public bool Activo { get; }

    // UDT-008: new properties
    public DateTime? FechaModificacion { get; }
    public DateTime? UltimoLogin { get; }
    public bool MustChangePassword { get; }

    public Usuario(
        int id,
        string username,
        string passwordHash,
        string nombre,
        string apellido,
        string? email,
        string rol,
        string permisosJson,
        bool activo,
        DateTime? fechaModificacion = null,
        DateTime? ultimoLogin = null,
        bool mustChangePassword = false)
    {
        Id = id;
        Username = username;
        PasswordHash = passwordHash;
        Nombre = nombre;
        Apellido = apellido;
        Email = email;
        Rol = rol;
        PermisosJson = permisosJson;
        Activo = activo;
        FechaModificacion = fechaModificacion;
        UltimoLogin = ultimoLogin;
        MustChangePassword = mustChangePassword;
    }

    /// <summary>
    /// Factory for creating a new user (no Id — DB assigns via IDENTITY).
    /// Defaults: Activo=true, PermisosJson={"grant":[],"deny":[]}, MustChangePassword=false.
    /// </summary>
    public static Usuario ForCreation(
        string username,
        string passwordHash,
        string nombre,
        string apellido,
        string? email,
        string rol)
    {
        return new Usuario(
            id: 0,
            username: username,
            passwordHash: passwordHash,
            nombre: nombre,
            apellido: apellido,
            email: email,
            rol: rol,
            permisosJson: """{"grant":[],"deny":[]}""",
            activo: true,
            fechaModificacion: null,
            ultimoLogin: null,
            mustChangePassword: false);
    }

    // ── UDT-008: copy-with factory methods ────────────────────────────────────

    /// <summary>
    /// Returns a new instance with updated profile fields.
    /// Caller is responsible for passing the current UTC timestamp via TimeProvider.GetUtcNow().UtcDateTime.
    /// Username and PasswordHash are immutable.
    /// </summary>
    public Usuario WithUpdatedProfile(string nombre, string apellido, string? email, string rol, bool activo, DateTime now)
        => new(
            id: Id,
            username: Username,
            passwordHash: PasswordHash,
            nombre: nombre,
            apellido: apellido,
            email: email,
            rol: rol,
            permisosJson: PermisosJson,
            activo: activo,
            fechaModificacion: now,
            ultimoLogin: UltimoLogin,
            mustChangePassword: MustChangePassword);

    /// <summary>
    /// Returns a new instance with a new password hash and mustChangePassword flag.
    /// Caller is responsible for passing the current UTC timestamp via TimeProvider.GetUtcNow().UtcDateTime.
    /// </summary>
    public Usuario WithNewPasswordHash(string hash, bool mustChangePassword, DateTime now)
        => new(
            id: Id,
            username: Username,
            passwordHash: hash,
            nombre: Nombre,
            apellido: Apellido,
            email: Email,
            rol: Rol,
            permisosJson: PermisosJson,
            activo: Activo,
            fechaModificacion: now,
            ultimoLogin: UltimoLogin,
            mustChangePassword: mustChangePassword);

    /// <summary>
    /// Returns a new instance with only the MustChangePassword flag changed.
    /// Caller is responsible for passing the current UTC timestamp via TimeProvider.GetUtcNow().UtcDateTime.
    /// </summary>
    public Usuario WithMustChangePassword(bool value, DateTime now)
        => new(
            id: Id,
            username: Username,
            passwordHash: PasswordHash,
            nombre: Nombre,
            apellido: Apellido,
            email: Email,
            rol: Rol,
            permisosJson: PermisosJson,
            activo: Activo,
            fechaModificacion: now,
            ultimoLogin: UltimoLogin,
            mustChangePassword: value);

    /// <summary>
    /// UDT-009: Returns a new instance with PermisosJson replaced.
    /// Caller is responsible for passing the current UTC timestamp via TimeProvider.GetUtcNow().UtcDateTime.
    /// Accepts raw JSON string so Domain stays free of Application dependencies.
    /// </summary>
    public Usuario WithPermisosJson(string permisosJson, DateTime now)
        => new(
            id: Id,
            username: Username,
            passwordHash: PasswordHash,
            nombre: Nombre,
            apellido: Apellido,
            email: Email,
            rol: Rol,
            permisosJson: permisosJson,
            activo: Activo,
            fechaModificacion: now,
            ultimoLogin: UltimoLogin,
            mustChangePassword: MustChangePassword);

    /// <summary>
    /// Returns a new instance with only UltimoLogin updated.
    /// Does NOT touch FechaModificacion.
    /// </summary>
    public Usuario WithUltimoLogin(DateTime utcNow)
        => new(
            id: Id,
            username: Username,
            passwordHash: PasswordHash,
            nombre: Nombre,
            apellido: Apellido,
            email: Email,
            rol: Rol,
            permisosJson: PermisosJson,
            activo: Activo,
            fechaModificacion: FechaModificacion,
            ultimoLogin: utcNow,
            mustChangePassword: MustChangePassword);
}
