using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using Tiku.Application.TenantAdmin;
using Tiku.Domain.Common;

namespace Tiku.Api.Contracts;

public sealed class TenantAdminClassQueryDto
{
    public Guid? RegionId { get; set; }
    public string? Status { get; set; }
    public string? Keyword { get; set; }

    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminClassFilter ToFilter()
    {
        return new TenantAdminClassFilter(RegionId, Status, Keyword, Limit);
    }
}

public sealed class TenantAdminClassMemberQueryDto
{
    [Required]
    public Guid ClassId { get; set; }

    public string? MemberType { get; set; }
    public string? Status { get; set; }

    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminClassMemberFilter ToFilter()
    {
        return new TenantAdminClassMemberFilter(ClassId, MemberType, Status, Limit);
    }
}

public sealed class TenantAdminStudentQueryDto
{
    public Guid? RegionId { get; set; }
    public Guid? ClassId { get; set; }
    public string? Status { get; set; }
    public string? Keyword { get; set; }

    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminStudentFilter ToFilter()
    {
        return new TenantAdminStudentFilter(RegionId, ClassId, Status, Keyword, Limit);
    }
}

public sealed class TenantAdminStudentActivityQueryDto
{
    public Guid? StudentUserId { get; set; }
    public string? Status { get; set; }

    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminStudentActivityFilter ToFilter()
    {
        return new TenantAdminStudentActivityFilter(StudentUserId, Status, Limit);
    }
}

public sealed class TenantAdminMemberQueryDto
{
    public string? Role { get; set; }
    public string? Status { get; set; }
    public string? Keyword { get; set; }

    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminMemberFilter ToFilter()
    {
        return new TenantAdminMemberFilter(Role, Status, Keyword, Limit);
    }
}

public sealed class TenantAdminAuditLogQueryDto
{
    public string? Action { get; set; }
    public string? TargetType { get; set; }
    public Guid? ActorUserId { get; set; }

    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminAuditLogFilter ToFilter()
    {
        return new TenantAdminAuditLogFilter(Action, TargetType, ActorUserId, Limit);
    }
}

public sealed class TenantAdminBadgeQueryDto
{
    public string? Category { get; set; }
    public bool IncludeInactive { get; set; }

    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminBadgeFilter ToFilter()
    {
        return new TenantAdminBadgeFilter(Category, IncludeInactive, Limit);
    }
}

public sealed class TenantAdminBadgeGrantQueryDto
{
    public Guid? UserId { get; set; }
    public Guid? BadgeId { get; set; }

    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminBadgeGrantFilter ToFilter()
    {
        return new TenantAdminBadgeGrantFilter(UserId, BadgeId, Limit);
    }
}

public sealed class TenantAdminNotificationQueryDto
{
    public Guid? UserId { get; set; }
    public string? Status { get; set; }
    public string? NotificationType { get; set; }

    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminNotificationFilter ToFilter()
    {
        return new TenantAdminNotificationFilter(UserId, Status, NotificationType, Limit);
    }
}

public sealed class TenantAdminFeedbackQueryDto
{
    public Guid? UserId { get; set; }
    public string? Status { get; set; }
    public string? Type { get; set; }
    public string? Keyword { get; set; }

    [Range(1, 500)]
    public int? Limit { get; set; }

    public TenantAdminFeedbackFilter ToFilter()
    {
        return new TenantAdminFeedbackFilter(UserId, Status, Type, Keyword, Limit);
    }
}

public sealed class UpsertTenantAdminClassDto
{
    public Guid? Id { get; set; }
    public Guid? RegionId { get; set; }
    public string? LegacyId { get; set; }
    public string? Code { get; set; }
    public required string Name { get; set; }
    public string? Description { get; set; }
    public string? Status { get; set; }
    public int? Order { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertTenantAdminClassCommand ToCommand()
    {
        return new UpsertTenantAdminClassCommand(Id, RegionId, LegacyId, Code, Name, Description, Status, Order, Metadata);
    }
}

public sealed class TenantAdminUserLookupDto
{
    public Guid? UserId { get; set; }
    public string? Username { get; set; }
    public string? Email { get; set; }
    public string? Phone { get; set; }
    public string? Name { get; set; }
    public string? AvatarUrl { get; set; }

    public UserLookupCommand ToCommand()
    {
        return new UserLookupCommand(UserId, Username, Email, Phone, Name, AvatarUrl);
    }
}

public sealed class UpsertTenantAdminClassMemberDto
{
    [Required]
    public Guid ClassId { get; set; }

    public TenantAdminUserLookupDto User { get; set; } = new();
    public string? MemberType { get; set; }
    public string? Status { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertTenantAdminClassMemberCommand ToCommand()
    {
        return new UpsertTenantAdminClassMemberCommand(ClassId, User.ToCommand(), MemberType, Status, Metadata);
    }
}

public sealed class RemoveTenantAdminClassMemberDto
{
    [Required]
    public Guid ClassMemberId { get; set; }
}

public sealed class UpsertTenantAdminStudentDto
{
    public TenantAdminUserLookupDto User { get; set; } = new();
    public Guid? RegionId { get; set; }
    public Guid? SelectedSchoolId { get; set; }
    public Guid? SelectedMajorId { get; set; }
    public string? AvatarPreset { get; set; }
    public JsonElement Stats { get; set; } = JsonDefaults.Object();
    public JsonElement Progress { get; set; } = JsonDefaults.Object();
    public JsonElement ModuleSelections { get; set; } = JsonDefaults.Object();
    public JsonElement RawProfile { get; set; } = JsonDefaults.Object();

    public UpsertTenantAdminStudentCommand ToCommand()
    {
        return new UpsertTenantAdminStudentCommand(
            User.ToCommand(),
            RegionId,
            SelectedSchoolId,
            SelectedMajorId,
            AvatarPreset,
            Stats,
            Progress,
            ModuleSelections,
            RawProfile);
    }
}

public sealed class UpdateTenantAdminStudentStatusDto
{
    [Required]
    public Guid UserId { get; set; }

    public string? Status { get; set; }
    public string? Reason { get; set; }

    public UpdateTenantAdminStudentStatusCommand ToCommand()
    {
        return new UpdateTenantAdminStudentStatusCommand(UserId, Status, Reason);
    }
}

public sealed class TenantAdminStudentImportRowDto
{
    public TenantAdminUserLookupDto User { get; set; } = new();
    public Guid? RegionId { get; set; }
    public Guid? ClassId { get; set; }
    public string? AvatarPreset { get; set; }
    public JsonElement RawProfile { get; set; } = JsonDefaults.Object();

    public TenantAdminStudentImportRowCommand ToCommand()
    {
        return new TenantAdminStudentImportRowCommand(User.ToCommand(), RegionId, ClassId, AvatarPreset, RawProfile);
    }
}

public sealed class TenantAdminStudentImportDto
{
    [Required]
    public IReadOnlyCollection<TenantAdminStudentImportRowDto> Rows { get; set; } = [];

    public TenantAdminStudentImportCommand ToCommand()
    {
        return new TenantAdminStudentImportCommand(Rows.Select(row => row.ToCommand()).ToArray());
    }
}

public sealed class TenantAdminBulkAssignClassDto
{
    [Required]
    public Guid ClassId { get; set; }

    [Required]
    public IReadOnlyCollection<Guid> UserIds { get; set; } = [];

    public TenantAdminBulkAssignClassCommand ToCommand()
    {
        return new TenantAdminBulkAssignClassCommand(ClassId, UserIds);
    }
}

public sealed class TenantAdminBulkStatusDto
{
    [Required]
    public IReadOnlyCollection<Guid> UserIds { get; set; } = [];

    public string? Status { get; set; }

    [StringLength(1000)]
    public string? Reason { get; set; }

    public TenantAdminBulkStatusCommand ToCommand()
    {
        return new TenantAdminBulkStatusCommand(UserIds, Status, Reason);
    }
}

public sealed class UpsertTenantSupervisionRuleDto
{
    [Required]
    [StringLength(100)]
    public string Code { get; set; } = string.Empty;

    [Required]
    [StringLength(200)]
    public string Title { get; set; } = string.Empty;

    public bool Enabled { get; set; } = true;

    [Range(0, 3650)]
    public int? DaysWithoutCheckIn { get; set; }

    [Range(0, int.MaxValue)]
    public int? MaxQuestionsAnsweredToday { get; set; }

    [StringLength(50)]
    public string? FollowupType { get; set; }

    [StringLength(50)]
    public string? Priority { get; set; }

    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertTenantSupervisionRuleCommand ToCommand()
    {
        return new UpsertTenantSupervisionRuleCommand(
            Code,
            Title,
            Enabled,
            DaysWithoutCheckIn,
            MaxQuestionsAnsweredToday,
            FollowupType,
            Priority,
            Metadata);
    }
}

public sealed class TenantSupervisionGenerateDto
{
    public IReadOnlyCollection<Guid>? UserIds { get; set; }
    public Guid? AssignedToUserId { get; set; }
    public DateTimeOffset? DueAt { get; set; }

    public TenantSupervisionGenerateCommand ToCommand()
    {
        return new TenantSupervisionGenerateCommand(UserIds, AssignedToUserId, DueAt);
    }
}

public sealed class UpsertTenantAdminStudentNoteDto
{
    public Guid? Id { get; set; }

    [Required]
    public Guid StudentUserId { get; set; }

    public string? NoteType { get; set; }
    public required string Content { get; set; }
    public string? Visibility { get; set; }
    public bool? IsPinned { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertTenantAdminStudentNoteCommand ToCommand()
    {
        return new UpsertTenantAdminStudentNoteCommand(Id, StudentUserId, NoteType, Content, Visibility, IsPinned, Metadata);
    }
}

public sealed class UpsertTenantAdminStudentFollowupDto
{
    public Guid? Id { get; set; }

    [Required]
    public Guid StudentUserId { get; set; }

    public Guid? AssignedToUserId { get; set; }
    public Guid? ClassId { get; set; }
    public required string Title { get; set; }
    public string? Description { get; set; }
    public string? FollowupType { get; set; }
    public string? Priority { get; set; }
    public string? Status { get; set; }
    public DateTimeOffset? DueAt { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertTenantAdminStudentFollowupCommand ToCommand()
    {
        return new UpsertTenantAdminStudentFollowupCommand(
            Id,
            StudentUserId,
            AssignedToUserId,
            ClassId,
            Title,
            Description,
            FollowupType,
            Priority,
            Status,
            DueAt,
            Metadata);
    }
}

public sealed class UpsertTenantAdminMemberDto
{
    public Guid? MembershipId { get; set; }
    public TenantAdminUserLookupDto User { get; set; } = new();
    public string? Role { get; set; }
    public string? Status { get; set; }
    public string? PrimaryRole { get; set; }

    public UpsertTenantAdminMemberCommand ToCommand()
    {
        return new UpsertTenantAdminMemberCommand(MembershipId, User.ToCommand(), Role, Status, PrimaryRole);
    }
}

public sealed class DisableTenantAdminMemberDto
{
    [Required]
    public Guid MembershipId { get; set; }
}

public sealed class UpsertTenantBrandingDto
{
    public required string BrandName { get; set; }
    public string? ShortName { get; set; }
    public string? Slogan { get; set; }
    public string? OrganizationName { get; set; }
    public string? LogoUrl { get; set; }
    public string? FaviconUrl { get; set; }
    public string? ServiceWechat { get; set; }
    public string? ServiceAccountName { get; set; }

    public UpsertTenantBrandingCommand ToCommand()
    {
        return new UpsertTenantBrandingCommand(
            BrandName,
            ShortName,
            Slogan,
            OrganizationName,
            LogoUrl,
            FaviconUrl,
            ServiceWechat,
            ServiceAccountName);
    }
}

public sealed class UpsertTenantSettingsDto
{
    public JsonElement FeatureFlags { get; set; } = JsonDefaults.Object();
    public JsonElement AdminFeatureFlags { get; set; } = JsonDefaults.Object();
    public JsonElement PublicConfig { get; set; } = JsonDefaults.Object();

    public UpsertTenantSettingsCommand ToCommand()
    {
        return new UpsertTenantSettingsCommand(FeatureFlags, AdminFeatureFlags, PublicConfig);
    }
}

public sealed class PreviewTenantThemeDto
{
    public required string TemplateCode { get; set; }
    public JsonElement Theme { get; set; } = JsonDefaults.Object();
    public JsonElement PublicAssets { get; set; } = JsonDefaults.Object();

    public PreviewTenantThemeCommand ToCommand()
    {
        return new PreviewTenantThemeCommand(TemplateCode, Theme, PublicAssets);
    }
}

public sealed class PublishTenantThemeDto
{
    public bool? UseDraft { get; set; }
    public string? TemplateCode { get; set; }
    public JsonElement Theme { get; set; } = JsonDefaults.Object();
    public JsonElement PublicAssets { get; set; } = JsonDefaults.Object();

    public PublishTenantThemeCommand ToCommand()
    {
        return new PublishTenantThemeCommand(UseDraft ?? true, TemplateCode, Theme, PublicAssets);
    }
}

public sealed class CreateTenantDomainDto
{
    public required string Host { get; set; }
    public string? DomainType { get; set; }
    public bool IsPrimary { get; set; }

    public CreateTenantDomainCommand ToCommand()
    {
        return new CreateTenantDomainCommand(Host, DomainType, IsPrimary);
    }
}

public sealed class UpsertTenantIdentityProviderDto
{
    public required string Provider { get; set; }
    public string? Status { get; set; }
    public string? DisplayName { get; set; }
    public string? SecretRef { get; set; }
    public int? Priority { get; set; }
    public JsonElement ConfigPublic { get; set; } = JsonDefaults.Object();

    public UpsertTenantIdentityProviderCommand ToCommand()
    {
        return new UpsertTenantIdentityProviderCommand(Provider, Status, DisplayName, SecretRef, Priority, ConfigPublic);
    }
}

public sealed class UpsertTenantAdminBadgeDto
{
    public Guid? Id { get; set; }
    public string? LegacyId { get; set; }
    public required string Name { get; set; }
    public string? Description { get; set; }
    public string? Category { get; set; }
    public string? IconUrl { get; set; }
    public int? Level { get; set; }
    public string? UnlockType { get; set; }
    public string? ConditionField { get; set; }
    public string? ConditionOperator { get; set; }
    public decimal? ConditionValue { get; set; }
    public JsonElement ConditionExtra { get; set; } = JsonDefaults.Object();
    public int? Order { get; set; }
    public bool? IsActive { get; set; }

    public UpsertTenantAdminBadgeCommand ToCommand()
    {
        return new UpsertTenantAdminBadgeCommand(
            Id,
            LegacyId,
            Name,
            Description,
            Category,
            IconUrl,
            Level,
            UnlockType,
            ConditionField,
            ConditionOperator,
            ConditionValue,
            ConditionExtra,
            Order,
            IsActive);
    }
}

public sealed class GrantTenantAdminBadgeDto
{
    [Required]
    public Guid UserId { get; set; }

    [Required]
    public Guid BadgeId { get; set; }

    public string? LegacyId { get; set; }
    public string? Note { get; set; }
    public DateTimeOffset? GrantedAt { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public GrantTenantAdminBadgeCommand ToCommand()
    {
        return new GrantTenantAdminBadgeCommand(UserId, BadgeId, LegacyId, Note, GrantedAt, Metadata);
    }
}

public sealed class UpsertTenantAdminNotificationDto
{
    [Required]
    public Guid UserId { get; set; }

    public required string NotificationType { get; set; }
    public string? Severity { get; set; }
    public required string Title { get; set; }
    public required string Message { get; set; }
    public string? ActionLabel { get; set; }
    public string? ActionPath { get; set; }
    public string? SourceType { get; set; }
    public Guid? SourceId { get; set; }
    public string? DedupeKey { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertTenantAdminNotificationCommand ToCommand()
    {
        return new UpsertTenantAdminNotificationCommand(
            UserId,
            NotificationType,
            Severity,
            Title,
            Message,
            ActionLabel,
            ActionPath,
            SourceType,
            SourceId,
            DedupeKey,
            Metadata);
    }
}

public sealed class UpdateTenantAdminFeedbackDto
{
    [Required]
    public Guid FeedbackId { get; set; }

    public string? Status { get; set; }
    public string? Priority { get; set; }
    public string? Resolution { get; set; }
    public string? Note { get; set; }
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpdateTenantAdminFeedbackCommand ToCommand()
    {
        return new UpdateTenantAdminFeedbackCommand(FeedbackId, Status, Priority, Resolution, Note, Metadata);
    }
}
