using System.Text.Json;
using Tiku.Domain.Common;

namespace Tiku.Domain.Tenancy;

public sealed class TenantExternalProvider : AuditableTenantEntity
{
    public TenantExternalProviderCapability Capability { get; set; } = TenantExternalProviderCapability.Identity;
    public string Provider { get; set; } = string.Empty;
    public TenantExternalProviderStatus Status { get; set; } = TenantExternalProviderStatus.Disabled;
    public string? DisplayName { get; set; }
    public string? SecretRef { get; set; }
    public int Priority { get; set; } = 100;
    public JsonElement ConfigPublic { get; set; } = JsonDefaults.Object();
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}

public sealed class TenantSecret : AuditableTenantEntity
{
    public string Purpose { get; set; } = string.Empty;
    public string Provider { get; set; } = string.Empty;
    public string SecretKey { get; set; } = string.Empty;
    public string SecretRef { get; set; } = string.Empty;
    public TenantSecretStatus Status { get; set; } = TenantSecretStatus.Active;
    public string EncryptionKeyId { get; set; } = string.Empty;
    public byte[] EncryptedPayload { get; set; } = [];
    public byte[] EncryptionNonce { get; set; } = [];
    public byte[] EncryptionTag { get; set; } = [];
    public DateTimeOffset? RotatedAt { get; set; }
    public DateTimeOffset? ExpiresAt { get; set; }
}

public sealed class SmsVerificationCode : Entity, ITenantOwned
{
    public string Phone { get; set; } = string.Empty;
    public SmsPurpose Purpose { get; set; } = SmsPurpose.Login;
    public string CodeHash { get; set; } = string.Empty;
    public string Provider { get; set; } = "mock";
    public SmsVerificationStatus Status { get; set; } = SmsVerificationStatus.Pending;
    public int Attempts { get; set; }
    public DateTimeOffset ExpiresAt { get; set; }
    public DateTimeOffset? ConsumedAt { get; set; }
    public string? IpAddress { get; set; }
    public string? UserAgent { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
    public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
    public Guid TenantId { get; set; }
}

public sealed class AuthLoginEvent : Entity
{
    public Guid? TenantId { get; set; }
    public Guid? UserId { get; set; }
    public string Provider { get; set; } = string.Empty;
    public string? Identifier { get; set; }
    public AuthLoginResult Result { get; set; } = AuthLoginResult.Failed;
    public string? FailureCode { get; set; }
    public string? IpAddress { get; set; }
    public string? UserAgent { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
    public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
}

public sealed class AuthSession : AuditableEntity
{
    public AuthRealm Realm { get; set; } = AuthRealm.Tenant;
    public Guid? TenantId { get; set; }
    public Guid UserId { get; set; }
    public Guid TokenFamilyId { get; set; }
    public Guid? ParentSessionId { get; set; }
    public Guid? ReplacedBySessionId { get; set; }
    public string TokenHash { get; set; } = string.Empty;
    public string SecurityStamp { get; set; } = string.Empty;
    public string Provider { get; set; } = string.Empty;
    public DateTimeOffset ExpiresAt { get; set; }
    public DateTimeOffset? RevokedAt { get; set; }
    public string? RevokedReason { get; set; }
    public string? IpAddress { get; set; }
    public string? UserAgent { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}

public enum AuthRealm
{
    Tenant,
    Platform
}

public sealed class AuthChallenge : Entity
{
    public Guid UserId { get; set; }
    public AuthRealm Realm { get; set; }
    public Guid? TenantId { get; set; }
    public AuthChallengePurpose Purpose { get; set; }
    public string TokenHash { get; set; } = string.Empty;
    public string SecurityStamp { get; set; } = string.Empty;
    public string Provider { get; set; } = string.Empty;
    public DateTimeOffset ExpiresAt { get; set; }
    public DateTimeOffset? ConsumedAt { get; set; }
    public string? IpAddress { get; set; }
    public string? UserAgent { get; set; }
    public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
}

public enum AuthChallengePurpose
{
    PasswordChange
}

public sealed class SmsSendRateLimit : ITenantOwned
{
    public SmsRateLimitDimension Dimension { get; set; } = SmsRateLimitDimension.Phone;
    public string ScopeHash { get; set; } = string.Empty;
    public DateTimeOffset BucketStart { get; set; }
    public int RequestCount { get; set; }
    public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.UtcNow;
    public Guid TenantId { get; set; }
}

public sealed class SmsChannel : AuditableTenantEntity
{
    public string Provider { get; set; } = "generic";
    public string Name { get; set; } = string.Empty;
    public string Signature { get; set; } = string.Empty;
    public string Scene { get; set; } = "login";
    public TenantExternalProviderStatus Status { get; set; } = TenantExternalProviderStatus.Disabled;
    public string? SecretRef { get; set; }
    public int Priority { get; set; } = 100;
    public int MonthlyQuota { get; set; }
    public JsonElement ConfigPublic { get; set; } = JsonDefaults.Object();
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}

public sealed class SmsTemplate : AuditableTenantEntity
{
    public Guid ChannelId { get; set; }
    public string Code { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public SmsTemplateType Type { get; set; } = SmsTemplateType.Notification;
    public SmsTemplateAuditStatus AuditStatus { get; set; } = SmsTemplateAuditStatus.Draft;
    public SmsTemplateStatus Status { get; set; } = SmsTemplateStatus.Active;
    public string? ProviderTemplateCode { get; set; }
    public string Content { get; set; } = string.Empty;
    public string? Remark { get; set; }
    public DateTimeOffset? SubmittedAt { get; set; }
    public DateTimeOffset? ApprovedAt { get; set; }
    public DateTimeOffset? DisabledAt { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}

public sealed class SmsSendLog : Entity, ITenantOwned
{
    public Guid? ChannelId { get; set; }
    public Guid? TemplateId { get; set; }
    public string Provider { get; set; } = "generic";
    public string Scene { get; set; } = string.Empty;
    public string? PhoneMasked { get; set; }
    public SmsSendLogStatus Status { get; set; } = SmsSendLogStatus.Pending;
    public string? ProviderMessageId { get; set; }
    public string? ErrorCode { get; set; }
    public string? ErrorMessage { get; set; }
    public DateTimeOffset? SentAt { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
    public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
    public Guid TenantId { get; set; }
}

public sealed class TenantClass : AuditableTenantEntity
{
    public Guid? RegionId { get; set; }
    public string? LegacyId { get; set; }
    public string? Code { get; set; }
    public string Name { get; set; } = string.Empty;
    public string? Description { get; set; }
    public TenantRecordStatus Status { get; set; } = TenantRecordStatus.Active;
    public int SortOrder { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
    public Guid? CreatedBy { get; set; }
    public Guid? UpdatedBy { get; set; }
}

public sealed class TenantClassMember : AuditableTenantEntity
{
    public Guid ClassId { get; set; }
    public Guid UserId { get; set; }
    public TenantClassMemberType MemberType { get; set; } = TenantClassMemberType.Student;
    public TenantClassMemberStatus Status { get; set; } = TenantClassMemberStatus.Active;
    public DateTimeOffset JoinedAt { get; set; } = DateTimeOffset.UtcNow;
    public DateTimeOffset? LeftAt { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
    public Guid? CreatedBy { get; set; }
    public Guid? UpdatedBy { get; set; }
}

public sealed class TenantStudentNote : AuditableTenantEntity
{
    public Guid StudentUserId { get; set; }
    public StudentNoteType NoteType { get; set; } = StudentNoteType.General;
    public string Content { get; set; } = string.Empty;
    public StudentNoteVisibility Visibility { get; set; } = StudentNoteVisibility.TenantStaff;
    public bool IsPinned { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
    public Guid? CreatedBy { get; set; }
    public Guid? UpdatedBy { get; set; }
}

public sealed class TenantStudentFollowup : AuditableTenantEntity
{
    public Guid StudentUserId { get; set; }
    public Guid? AssignedToUserId { get; set; }
    public Guid? ClassId { get; set; }
    public string Title { get; set; } = string.Empty;
    public string? Description { get; set; }
    public StudentFollowupType FollowupType { get; set; } = StudentFollowupType.Learning;
    public StudentFollowupPriority Priority { get; set; } = StudentFollowupPriority.Normal;
    public StudentFollowupStatus Status { get; set; } = StudentFollowupStatus.Open;
    public DateTimeOffset? DueAt { get; set; }
    public DateTimeOffset? CompletedAt { get; set; }
    public Guid? CompletedBy { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();
    public Guid? CreatedBy { get; set; }
    public Guid? UpdatedBy { get; set; }
}

public enum TenantExternalProviderCapability
{
    Identity,
    ObjectStorage,
    Sms,
    Payment,
    Notification,
    Ai
}

public enum TenantExternalProviderStatus
{
    Active,
    Disabled,
    Testing
}

public enum TenantSecretStatus
{
    Active,
    Disabled,
    Rotating
}

public enum SmsPurpose
{
    Login,
    BindPhone,
    ResetPassword
}

public enum SmsVerificationStatus
{
    Pending,
    Sent,
    Verified,
    Expired,
    Blocked,
    Failed
}

public enum SmsTemplateType
{
    VerificationCode,
    Marketing,
    Notification
}

public enum SmsTemplateAuditStatus
{
    Draft,
    PendingReview,
    Approved,
    Rejected
}

public enum SmsTemplateStatus
{
    Active,
    Disabled
}

public enum SmsSendLogStatus
{
    Pending,
    Sent,
    Failed
}

public enum AuthLoginResult
{
    Sent,
    Success,
    Failed,
    Blocked
}

public enum SmsRateLimitDimension
{
    Tenant,
    Phone,
    Ip,
    Device
}

public enum TenantRecordStatus
{
    Active,
    Disabled,
    Archived
}

public enum TenantClassMemberType
{
    Student,
    Teacher,
    Assistant,
    HeadTeacher
}

public enum TenantClassMemberStatus
{
    Active,
    Disabled,
    Removed
}

public enum StudentNoteType
{
    General,
    Learning,
    Service,
    Sales,
    Risk,
    FollowUp
}

public enum StudentNoteVisibility
{
    TenantStaff,
    ClassStaff,
    AuthorOnly
}

public enum StudentFollowupType
{
    Learning,
    Service,
    Sales,
    Renewal,
    Risk,
    Custom
}

public enum StudentFollowupPriority
{
    Low,
    Normal,
    High,
    Urgent
}

public enum StudentFollowupStatus
{
    Open,
    InProgress,
    Done,
    Cancelled
}