using System.ComponentModel.DataAnnotations;
using System.Text.Json;

namespace ERPCore.Dtos.Auth;

/// <summary>Shared AuthHex user projection (API_REFERENCE.md §3). Field set is
/// AuthHex's best-documented subset; unknown fields are ignored on deserialize.</summary>
public sealed class UserSummaryDto
{
    public Guid? UserId { get; set; }
    public Guid? RoleId { get; set; }
    public Guid? UserTypeId { get; set; }
    public string? Fullname { get; set; }
    public string? UserName { get; set; }
    public string? Nic { get; set; }
    public string? Email { get; set; }
    public string? MobileNumber { get; set; }
    public bool? EmailVerified { get; set; }
    public bool? MobileNumberVerified { get; set; }
    public bool? IsActive { get; set; }
    public bool? IsLocked { get; set; }
}

/// <summary>Body returned by every session-issuing endpoint. Tokens never appear
/// here — they are delivered only as httpOnly cookies (docs/02-SECURITY.md §B.2).</summary>
public sealed class AuthSessionResponse
{
    public UserSummaryDto? User { get; set; }
    public int ExpiresIn { get; set; }
}

public sealed class RegisterRequest
{
    /// <summary>Optional — AuthHex requires a client-supplied id; ERPCore generates one when omitted.</summary>
    public Guid? UserId { get; set; }
    [Required] public Guid RoleId { get; set; }
    [Required] public Guid UserTypeId { get; set; }
    public string? Fullname { get; set; }
    public string? UserName { get; set; }
    public string? Nic { get; set; }
    public string? Email { get; set; }
    public string? MobileNumber { get; set; }
    public string? Password { get; set; }
    public string? DeviceName { get; set; }
    public bool? ChkUser { get; set; }
}

public sealed class LoginRequest
{
    [Required] public string Identifier { get; set; } = string.Empty;
    [Required] public string Password { get; set; } = string.Empty;
    public Guid? UserTypeId { get; set; }
    public string? DeviceName { get; set; }
}

public sealed class VerifyOtpForLoginRequest
{
    [Required] public string ReferenceNumber { get; set; } = string.Empty;
    [Required] public string OtpCode { get; set; } = string.Empty;
    public string? DeviceName { get; set; }
}

public sealed class OtpLoginVerifiedResponse
{
    public string? ReferenceNumber { get; set; }
    public Guid? UserId { get; set; }
    public bool Verified { get; set; }
    public UserSummaryDto? User { get; set; }
    public int ExpiresIn { get; set; }
}

public sealed class RefreshTokenRequest
{
    public string? DeviceName { get; set; }
}

public sealed class GetUserDetailsResponse
{
    public UserSummaryDto? User { get; set; }
    /// <summary>Passed through as-is — AuthHex's Role/UserType shapes aren't in the documented catalog.</summary>
    public JsonElement? Role { get; set; }
    public JsonElement? UserType { get; set; }
}

/// <summary>AuthHex's UserType lookup (ERP_Auth_Service/API_DOCUMENTATION.md, listUserTypes).</summary>
public sealed class UserTypeDto
{
    public Guid UserTypeId { get; set; }
    public string? Code { get; set; }
    public string? Description { get; set; }
}

public sealed class SessionDto
{
    public string? SessionId { get; set; }
    public string? DeviceName { get; set; }
    public string? Browser { get; set; }
    public string? OS { get; set; }
    public string? IPAddress { get; set; }
    public DateTime? CreatedAt { get; set; }
    public DateTime? ExpiresAt { get; set; }
    public DateTime? RevokedAt { get; set; }
    public bool? IsActive { get; set; }
}

public sealed class ChangeUserStatusRequest
{
    [Required] public bool IsActive { get; set; }
}

public sealed class LockUserAccountRequest
{
    [Required] public bool IsLocked { get; set; }
}

public sealed class ChangeUserPasswordRequest
{
    [Required] public string CurrentPassword { get; set; } = string.Empty;
    [Required, MinLength(8)] public string NewPassword { get; set; } = string.Empty;
}

public sealed class VerifyPasswordRequest
{
    [Required] public string Password { get; set; } = string.Empty;
}

public sealed class VerifyPasswordResponse
{
    public bool Valid { get; set; }
}

public sealed class UpdateUserRequest
{
    public string? FullName { get; set; }
    public string? UserName { get; set; }
    public string? Nic { get; set; }
    public string? Address { get; set; }
    public string? Optional1 { get; set; }
    public string? Optional2 { get; set; }
    public string? Email { get; set; }
    public string? MobileNumber { get; set; }
    public string? NewPassword { get; set; }
    public string? CurrentPassword { get; set; }
}

/// <summary>Passthrough — TOTP secret/QR payload shape is only loosely documented
/// ("secret key, QR/otpauth URL ... from the third-party service").</summary>
public sealed class TwoFaSetupResponse
{
    public JsonElement Data { get; set; }
}

public sealed class CompleteTwoFaSetupRequest
{
    [Required] public string SecretKey { get; set; } = string.Empty;
    [Required] public string VerificationCode { get; set; } = string.Empty;
}

public sealed class CompleteTwoFaSetupResponse
{
    public List<string> BackupCodes { get; set; } = new();
    public UserSummaryDto? User { get; set; }
}

public sealed class VerifyTwoFaRequest
{
    [Required] public string VerificationCode { get; set; } = string.Empty;
}

public sealed class DisableTwoFaRequest
{
    [Required] public string VerificationCode { get; set; } = string.Empty;
}

public sealed class TwoFaStatusResponse
{
    public bool IsMfaEnabled { get; set; }
    public bool IsVerified { get; set; }
    public DateTime? LastUsedAt { get; set; }
    public DateTime? VerifiedAt { get; set; }
    public bool HasBackupCodes { get; set; }
}

public sealed class LogoutRequest
{
    /// <summary>
    /// Optional: AuthHex returns no <c>userId</c> on login, so browsers cannot supply one.
    /// When omitted, the controller resolves it from the session token's UserId claim.
    /// </summary>
    public Guid? UserId { get; set; }
}
