using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using Tiku.Application.PlatformAdmin;
using Tiku.Domain.Common;
using Tiku.Domain.Commerce;
using Tiku.Domain.Identity;
using Tiku.Domain.Platform;
using Tiku.Domain.Tenancy;

namespace Tiku.Api.Contracts;

public sealed class PlatformAdminQueryDto
{
    [StringLength(32)]
    public string? Status { get; set; }

    [StringLength(200)]
    public string? Search { get; set; }

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

    public PlatformAdminQuery ToQuery() => new(Status, Search, Limit);
}

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

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

    [StringLength(300)]
    public string? LegalName { get; set; }

    public TenantStatus Status { get; set; } = TenantStatus.Active;
    public BillingStatus BillingStatus { get; set; } = BillingStatus.Trial;
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public CreatePlatformTenantCommand ToCommand() => new(Slug, Name, LegalName, Status, BillingStatus, Metadata);
}

public sealed class UpdatePlatformTenantStatusDto
{
    [Required]
    public Guid TenantId { get; set; }

    public TenantStatus Status { get; set; } = TenantStatus.Active;
    public BillingStatus BillingStatus { get; set; } = BillingStatus.Active;

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

    public UpdatePlatformTenantStatusCommand ToCommand() => new(TenantId, Status, BillingStatus, Reason);
}

public sealed class UpsertPlatformTenantBillingProfileDto
{
    [Required]
    public Guid TenantId { get; set; }

    [StringLength(300)]
    public string? BillingName { get; set; }

    [StringLength(100)]
    public string? TaxId { get; set; }

    [StringLength(100)]
    public string? ContactName { get; set; }

    [StringLength(32)]
    public string? ContactPhone { get; set; }

    [StringLength(320)]
    public string? ContactEmail { get; set; }

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

    [StringLength(300)]
    public string? InvoiceTitle { get; set; }

    public TenantInvoiceTitleType? InvoiceType { get; set; }

    [StringLength(300)]
    public string? BankName { get; set; }

    [StringLength(100)]
    public string? BankAccountMasked { get; set; }

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

    public UpsertPlatformTenantBillingProfileCommand ToCommand() => new(
        TenantId,
        BillingName,
        TaxId,
        ContactName,
        ContactPhone,
        ContactEmail,
        BillingAddress,
        InvoiceTitle,
        InvoiceType,
        BankName,
        BankAccountMasked,
        Metadata);
}

public sealed class UpsertPlatformSubscriptionDto
{
    [Required]
    public Guid TenantId { get; set; }

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

    public TenantSubscriptionStatus Status { get; set; } = TenantSubscriptionStatus.Active;
    public DateTimeOffset? StartsAt { get; set; }
    public DateTimeOffset? ExpiresAt { get; set; }

    [StringLength(32)]
    public string? BillingCycle { get; set; }

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

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

    public UpsertPlatformSubscriptionCommand ToCommand() => new(
        TenantId,
        PlanCode,
        Status,
        StartsAt,
        ExpiresAt,
        BillingCycle,
        AmountCents,
        Metadata);
}

public sealed class UpsertPlatformStaffDto
{
    public Guid? UserId { get; set; }

    [StringLength(320)]
    public string? Email { get; set; }

    [StringLength(32)]
    public string? Phone { get; set; }

    [StringLength(200)]
    public string? Name { get; set; }

    public UserStatus Status { get; set; } = UserStatus.Active;
    public IReadOnlyCollection<Guid> RoleIds { get; set; } = [];

    public UpsertPlatformStaffCommand ToCommand() => new(UserId, Email, Phone, Name, Status, RoleIds);
}

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

    public UserStatus Status { get; set; } = UserStatus.Active;

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

    public UpdatePlatformStaffStatusCommand ToCommand() => new(UserId, Status, Reason);
}

public sealed class UpdatePlatformAuditAlertStatusDto
{
    [Required]
    public Guid AlertId { get; set; }

    public PlatformAuditAlertStatus Status { get; set; } = PlatformAuditAlertStatus.Acknowledged;

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

    public UpdatePlatformAuditAlertStatusCommand ToCommand() => new(AlertId, Status, ResolutionNote);
}

public sealed class UpsertPlatformDunningChannelDto
{
    public Guid? ChannelId { get; set; }

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

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

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

    public bool Enabled { get; set; } = true;
    public PlatformDunningProvider Provider { get; set; } = PlatformDunningProvider.Generic;

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

    [StringLength(300)]
    public string? SecretRef { get; set; }

    public IReadOnlyCollection<string> ReminderTypes { get; set; } = ["overdue", "final_notice"];
    public IReadOnlyCollection<string> ReminderChannels { get; set; } = ["internal"];

    [Range(1, 20)]
    public int MinReminderLevel { get; set; } = 1;

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

    [Range(1, 60)]
    public int TimeoutSeconds { get; set; } = 10;

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

    public UpsertPlatformDunningChannelCommand ToCommand() => new(
        ChannelId,
        ChannelCode,
        Name,
        Description,
        Enabled,
        Provider,
        WebhookUrl,
        SecretRef,
        ReminderTypes,
        ReminderChannels,
        MinReminderLevel,
        TenantIds,
        TimeoutSeconds,
        Metadata);
}

public sealed class DisablePlatformDunningChannelDto
{
    [Required]
    public Guid ChannelId { get; set; }

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

    public DisablePlatformDunningChannelCommand ToCommand() => new(ChannelId, Reason);
}

public sealed class RetryPlatformDunningEventDto
{
    [Required]
    public Guid EventId { get; set; }

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

    public RetryPlatformDunningEventCommand ToCommand() => new(EventId, Reason);
}
