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

namespace Tiku.Api.Contracts;

/// <summary>
///     租户交易查询参数。
/// </summary>
public sealed class TenantCommerceQueryDto
{
    /// <summary>
    ///     服务提供方。
    /// </summary>
    [StringLength(50)]
    public string? Provider { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    [StringLength(32)]
    public string? Status { get; set; }

    /// <summary>
    ///     返回数量上限。
    /// </summary>
    [Range(1, 200)]
    public int? Limit { get; set; }

    /// <summary>
    ///     用户 ID。
    /// </summary>
    public Guid? UserId { get; set; }

    /// <summary>
    ///     地区 ID。
    /// </summary>
    public Guid? RegionId { get; set; }
}

/// <summary>
///     新增或更新支付账号请求 DTO。
/// </summary>
public sealed class UpsertPaymentAccountDto
{
    /// <summary>
    ///     服务提供方。
    /// </summary>
    [Required]
    [StringLength(50)]
    public string Provider { get; set; } = string.Empty;

    /// <summary>
    ///     模式。
    /// </summary>
    [StringLength(50)]
    public string? Mode { get; set; } = "TenantCollect";

    /// <summary>
    ///     显示名称。
    /// </summary>
    [StringLength(200)]
    public string? DisplayName { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public TenantExternalProviderStatus Status { get; set; } = TenantExternalProviderStatus.Disabled;

    /// <summary>
    ///     密钥引用。
    /// </summary>
    [StringLength(300)]
    public string? SecretRef { get; set; }

    /// <summary>
    ///     优先级。
    /// </summary>
    public int? Priority { get; set; }

    /// <summary>
    ///     公开配置内容。
    /// </summary>
    public JsonElement ConfigPublic { get; set; } = JsonDefaults.Object();

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

/// <summary>
///     新增或更新租户Secret请求 DTO。
/// </summary>
public sealed class UpsertTenantSecretDto
{
    /// <summary>
    ///     用途。
    /// </summary>
    [Required]
    [StringLength(80)]
    public string Purpose { get; set; } = "payment";

    /// <summary>
    ///     服务提供方。
    /// </summary>
    [Required]
    [StringLength(50)]
    public string Provider { get; set; } = string.Empty;

    /// <summary>
    ///     密钥键。
    /// </summary>
    [Required]
    [StringLength(120)]
    public string SecretKey { get; set; } = string.Empty;

    /// <summary>
    ///     密钥引用。
    /// </summary>
    [StringLength(300)]
    public string SecretRef { get; set; } = string.Empty;

    /// <summary>
    ///     状态。
    /// </summary>
    public TenantSecretStatus Status { get; set; } = TenantSecretStatus.Active;

    /// <summary>
    ///     密钥载荷。
    /// </summary>
    public JsonElement SecretPayload { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     过期时间。
    /// </summary>
    public DateTimeOffset? ExpiresAt { get; set; }

    public UpsertTenantSecretCommand ToCommand()
    {
        return new UpsertTenantSecretCommand(
            Purpose,
            Provider,
            SecretKey,
            SecretRef,
            Status,
            SecretPayload,
            ExpiresAt);
    }
}

/// <summary>
///     创建编码批次请求 DTO。
/// </summary>
public sealed class CreateCodeBatchDto
{
    /// <summary>
    ///     名称。
    /// </summary>
    [Required]
    [StringLength(200)]
    public string Name { get; set; } = string.Empty;

    /// <summary>
    ///     总数量。
    /// </summary>
    [Range(1, 1000)]
    public int TotalCount { get; set; }

    /// <summary>
    ///     天数。
    /// </summary>
    [Range(1, 3650)]
    public int Days { get; set; }

    /// <summary>
    ///     地区 ID。
    /// </summary>
    public Guid? RegionId { get; set; }

    /// <summary>
    ///     售卖类型。
    /// </summary>
    [StringLength(50)]
    public string? SaleType { get; set; }

    /// <summary>
    ///     渠道。
    /// </summary>
    [StringLength(100)]
    public string? Channel { get; set; }

    /// <summary>
    ///     默认单价，单位为分。
    /// </summary>
    [Range(0, int.MaxValue)]
    public int? DefaultUnitPriceCents { get; set; }

    /// <summary>
    ///     成本价，单位为分。
    /// </summary>
    [Range(0, int.MaxValue)]
    public int? CostPriceCents { get; set; }

    /// <summary>
    ///     备注。
    /// </summary>
    [StringLength(1000)]
    public string? Remark { get; set; }

    public CreateCodeBatchCommand ToCommand()
    {
        return new CreateCodeBatchCommand(
            Name,
            TotalCount,
            Days,
            RegionId,
            SaleType,
            Channel,
            DefaultUnitPriceCents,
            CostPriceCents,
            Remark);
    }
}

/// <summary>
///     核销激活码编码请求 DTO。
/// </summary>
public sealed class RedeemActivationCodeDto
{
    /// <summary>
    ///     编码。
    /// </summary>
    [Required]
    [StringLength(100)]
    public string Code { get; set; } = string.Empty;

    /// <summary>
    ///     用户 ID。
    /// </summary>
    [Required]
    public Guid UserId { get; set; }

    /// <summary>
    ///     地区 ID。
    /// </summary>
    public Guid? RegionId { get; set; }

    public RedeemActivationCodeCommand ToCommand()
    {
        return new RedeemActivationCodeCommand(Code, UserId, RegionId);
    }
}

/// <summary>
///     新增或更新积分任务请求 DTO。
/// </summary>
public sealed class UpsertPointTaskDto
{
    /// <summary>
    ///     ID。
    /// </summary>
    public Guid? Id { get; set; }

    /// <summary>
    ///     任务键。
    /// </summary>
    [Required]
    [StringLength(100)]
    public string TaskKey { get; set; } = string.Empty;

    /// <summary>
    ///     标题。
    /// </summary>
    [Required]
    [StringLength(200)]
    public string Title { get; set; } = string.Empty;

    /// <summary>
    ///     说明。
    /// </summary>
    [StringLength(1000)]
    public string? Description { get; set; }

    /// <summary>
    ///     任务类型。
    /// </summary>
    public PointActivityTaskType TaskType { get; set; } = PointActivityTaskType.Manual;

    /// <summary>
    ///     状态。
    /// </summary>
    public PointActivityTaskStatus Status { get; set; } = PointActivityTaskStatus.Active;

    /// <summary>
    ///     积分数量。
    /// </summary>
    [Range(1, int.MaxValue)]
    public int Points { get; set; }

    /// <summary>
    ///     每用户最多领取次数。
    /// </summary>
    [Range(1, 1000)]
    public int MaxClaimsPerUser { get; set; } = 1;

    /// <summary>
    ///     开始时间。
    /// </summary>
    public DateTimeOffset? StartsAt { get; set; }

    /// <summary>
    ///     结束时间。
    /// </summary>
    public DateTimeOffset? EndsAt { get; set; }

    /// <summary>
    ///     排序值。
    /// </summary>
    public int SortOrder { get; set; }

    /// <summary>
    ///     规则配置。
    /// </summary>
    public JsonElement Rules { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertPointTaskCommand ToCommand()
    {
        return new UpsertPointTaskCommand(
            Id,
            TaskKey,
            Title,
            Description,
            TaskType,
            Status,
            Points,
            MaxClaimsPerUser,
            StartsAt,
            EndsAt,
            SortOrder,
            Rules,
            Metadata);
    }
}

/// <summary>
///     新增或更新积分兑换Item请求 DTO。
/// </summary>
public sealed class UpsertPointExchangeItemDto
{
    /// <summary>
    ///     ID。
    /// </summary>
    public Guid? Id { get; set; }

    /// <summary>
    ///     地区 ID。
    /// </summary>
    public Guid? RegionId { get; set; }

    /// <summary>
    ///     兑换项键。
    /// </summary>
    [Required]
    [StringLength(100)]
    public string ItemKey { get; set; } = string.Empty;

    /// <summary>
    ///     名称。
    /// </summary>
    [Required]
    [StringLength(200)]
    public string Name { get; set; } = string.Empty;

    /// <summary>
    ///     说明。
    /// </summary>
    [StringLength(1000)]
    public string? Description { get; set; }

    /// <summary>
    ///     兑换项类型。
    /// </summary>
    public PointExchangeItemType ItemType { get; set; } = PointExchangeItemType.Entitlement;

    /// <summary>
    ///     状态。
    /// </summary>
    public PointExchangeItemStatus Status { get; set; } = PointExchangeItemStatus.Active;

    /// <summary>
    ///     所需积分。
    /// </summary>
    [Range(1, int.MaxValue)]
    public int PointsCost { get; set; }

    /// <summary>
    ///     库存数量。
    /// </summary>
    [Range(0, int.MaxValue)]
    public int? Stock { get; set; }

    /// <summary>
    ///     天数。
    /// </summary>
    [Range(0, 3650)]
    public int? Days { get; set; }

    /// <summary>
    ///     排序值。
    /// </summary>
    public int SortOrder { get; set; }

    /// <summary>
    ///     开始时间。
    /// </summary>
    public DateTimeOffset? StartsAt { get; set; }

    /// <summary>
    ///     结束时间。
    /// </summary>
    public DateTimeOffset? EndsAt { get; set; }

    /// <summary>
    ///     履约载荷。
    /// </summary>
    public JsonElement FulfillmentPayload { get; set; } = JsonDefaults.Object();

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertPointExchangeItemCommand ToCommand()
    {
        return new UpsertPointExchangeItemCommand(
            Id,
            RegionId,
            ItemKey,
            Name,
            Description,
            ItemType,
            Status,
            PointsCost,
            Stock,
            Days,
            SortOrder,
            StartsAt,
            EndsAt,
            FulfillmentPayload,
            Metadata);
    }
}

/// <summary>
///     创建退款Request请求 DTO。
/// </summary>
public sealed class CreateRefundRequestDto
{
    /// <summary>
    ///     订单 ID。
    /// </summary>
    [Required]
    public Guid OrderId { get; set; }

    /// <summary>
    ///     支付记录 ID。
    /// </summary>
    public Guid? PaymentId { get; set; }

    /// <summary>
    ///     金额，单位为分。
    /// </summary>
    [Range(1, int.MaxValue)]
    public int AmountCents { get; set; }

    /// <summary>
    ///     原因。
    /// </summary>
    [StringLength(1000)]
    public string? Reason { get; set; }

    /// <summary>
    ///     权益动作。
    /// </summary>
    public RefundEntitlementAction EntitlementAction { get; set; } = RefundEntitlementAction.RevokeOnSuccess;

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public CreateRefundRequestCommand ToCommand()
    {
        return new CreateRefundRequestCommand(OrderId, PaymentId, AmountCents, Reason, EntitlementAction, Metadata);
    }
}

/// <summary>
///     更新退款状态请求 DTO。
/// </summary>
public sealed class UpdateRefundStatusDto
{
    /// <summary>
    ///     退款申请 ID。
    /// </summary>
    [Required]
    public Guid RefundRequestId { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public CommerceRefundStatus Status { get; set; }

    /// <summary>
    ///     原因。
    /// </summary>
    [StringLength(1000)]
    public string? Reason { get; set; }

    /// <summary>
    ///     渠道退款单号。
    /// </summary>
    [StringLength(200)]
    public string? ProviderRefundNo { get; set; }

    public UpdateRefundStatusCommand ToCommand()
    {
        return new UpdateRefundStatusCommand(RefundRequestId, Status, Reason, ProviderRefundNo);
    }
}

/// <summary>
///     创建对账批次请求 DTO。
/// </summary>
public sealed class CreateReconciliationBatchDto
{
    /// <summary>
    ///     服务提供方。
    /// </summary>
    [Required]
    [StringLength(50)]
    public string Provider { get; set; } = string.Empty;

    /// <summary>
    ///     账单日期。
    /// </summary>
    public DateOnly BillDate { get; set; }

    /// <summary>
    ///     账单类型。
    /// </summary>
    public ReconciliationBillType BillType { get; set; } = ReconciliationBillType.Combined;

    /// <summary>
    ///     来源。
    /// </summary>
    public ReconciliationSource Source { get; set; } = ReconciliationSource.ManualUpload;

    /// <summary>
    ///     来源名称。
    /// </summary>
    [StringLength(200)]
    public string? SourceName { get; set; }

    /// <summary>
    ///     来源哈希。
    /// </summary>
    [Required]
    [StringLength(200)]
    public string SourceHash { get; set; } = string.Empty;

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public CreateReconciliationBatchCommand ToCommand()
    {
        return new CreateReconciliationBatchCommand(Provider, BillDate, BillType, Source, SourceName, SourceHash,
            Metadata);
    }
}

/// <summary>
///     更新对账Issue请求 DTO。
/// </summary>
public sealed class UpdateReconciliationIssueDto
{
    /// <summary>
    ///     工单 ID。
    /// </summary>
    [Required]
    public Guid IssueId { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public ReconciliationIssueStatus Status { get; set; } = ReconciliationIssueStatus.Investigating;

    /// <summary>
    ///     处理类型。
    /// </summary>
    public ReconciliationResolutionType ResolutionType { get; set; } = ReconciliationResolutionType.None;

    /// <summary>
    ///     备注。
    /// </summary>
    [StringLength(1000)]
    public string? Note { get; set; }

    /// <summary>
    ///     分配处理人。
    /// </summary>
    public Guid? AssignedTo { get; set; }

    public UpdateReconciliationIssueCommand ToCommand()
    {
        return new UpdateReconciliationIssueCommand(IssueId, Status, ResolutionType, Note, AssignedTo);
    }
}

/// <summary>
///     预览对账导入请求 DTO。
/// </summary>
public sealed class PreviewReconciliationImportDto
{
    /// <summary>
    ///     服务提供方。
    /// </summary>
    [Required]
    [StringLength(50)]
    public string Provider { get; set; } = string.Empty;

    /// <summary>
    ///     账单日期。
    /// </summary>
    public DateOnly BillDate { get; set; }

    /// <summary>
    ///     账单类型。
    /// </summary>
    public ReconciliationBillType BillType { get; set; } = ReconciliationBillType.Combined;

    /// <summary>
    ///     来源名称。
    /// </summary>
    [Required]
    [StringLength(300)]
    public string SourceName { get; set; } = string.Empty;

    /// <summary>
    ///     数据行列表。
    /// </summary>
    public JsonElement Rows { get; set; } = JsonDefaults.Array();

    public PreviewReconciliationImportCommand ToPreviewCommand()
    {
        return new PreviewReconciliationImportCommand(Provider, BillDate, BillType, SourceName, Rows);
    }

    public ImportReconciliationCommand ToImportCommand()
    {
        return new ImportReconciliationCommand(Provider, BillDate, BillType, SourceName, Rows);
    }
}

/// <summary>
///     创建调账凭证请求 DTO。
/// </summary>
public sealed class CreateAdjustmentVoucherDto
{
    /// <summary>
    ///     工单 ID。
    /// </summary>
    public Guid? IssueId { get; set; }

    /// <summary>
    ///     批次 ID。
    /// </summary>
    public Guid? BatchId { get; set; }

    /// <summary>
    ///     兑换项 ID。
    /// </summary>
    public Guid? ItemId { get; set; }

    /// <summary>
    ///     订单 ID。
    /// </summary>
    public Guid? OrderId { get; set; }

    /// <summary>
    ///     支付记录 ID。
    /// </summary>
    public Guid? PaymentId { get; set; }

    /// <summary>
    ///     退款申请 ID。
    /// </summary>
    public Guid? RefundRequestId { get; set; }

    /// <summary>
    ///     方向。
    /// </summary>
    public CommerceAdjustmentDirection Direction { get; set; } = CommerceAdjustmentDirection.IncreaseRevenue;

    /// <summary>
    ///     金额，单位为分。
    /// </summary>
    [Range(1, int.MaxValue)]
    public int AmountCents { get; set; }

    /// <summary>
    ///     币种。
    /// </summary>
    [StringLength(10)]
    public string? Currency { get; set; }

    /// <summary>
    ///     原因。
    /// </summary>
    [Required]
    [StringLength(1000)]
    public string Reason { get; set; } = string.Empty;

    /// <summary>
    ///     证明资产键。
    /// </summary>
    [StringLength(500)]
    public string? ProofAssetKey { get; set; }

    /// <summary>
    ///     扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public CreateAdjustmentVoucherCommand ToCommand()
    {
        return new CreateAdjustmentVoucherCommand(
            IssueId,
            BatchId,
            ItemId,
            OrderId,
            PaymentId,
            RefundRequestId,
            Direction,
            AmountCents,
            Currency,
            Reason,
            ProofAssetKey,
            Metadata);
    }
}

/// <summary>
///     更新调账凭证状态请求 DTO。
/// </summary>
public sealed class UpdateAdjustmentVoucherStatusDto
{
    /// <summary>
    ///     凭证 ID。
    /// </summary>
    [Required]
    public Guid VoucherId { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public CommerceAdjustmentVoucherStatus Status { get; set; } = CommerceAdjustmentVoucherStatus.PendingReview;

    /// <summary>
    ///     备注。
    /// </summary>
    [StringLength(1000)]
    public string? Note { get; set; }

    public UpdateAdjustmentVoucherStatusCommand ToCommand()
    {
        return new UpdateAdjustmentVoucherStatusCommand(VoucherId, Status, Note);
    }
}

/// <summary>
///     RequestProviderBill任务请求 DTO。
/// </summary>
public sealed class RequestProviderBillJobDto
{
    /// <summary>
    ///     服务提供方。
    /// </summary>
    [Required]
    [StringLength(50)]
    public string Provider { get; set; } = string.Empty;

    /// <summary>
    ///     账单日期。
    /// </summary>
    public DateOnly BillDate { get; set; }

    /// <summary>
    ///     账单类型。
    /// </summary>
    public ReconciliationBillType BillType { get; set; } = ReconciliationBillType.Combined;

    /// <summary>
    ///     计划运行时间。
    /// </summary>
    public DateTimeOffset? RunAfter { get; set; }

    public RequestProviderBillJobCommand ToCommand()
    {
        return new RequestProviderBillJobCommand(Provider, BillDate, BillType, RunAfter);
    }
}

/// <summary>
///     退款通知请求 DTO。
/// </summary>
public sealed class RefundNotificationDto
{
    /// <summary>
    ///     退款单号。
    /// </summary>
    [Required]
    [StringLength(100)]
    public string RefundNo { get; set; } = string.Empty;

    /// <summary>
    ///     渠道退款单号。
    /// </summary>
    [StringLength(200)]
    public string? ProviderRefundNo { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public CommerceRefundStatus Status { get; set; } = CommerceRefundStatus.Succeeded;

    /// <summary>
    ///     事件 ID。
    /// </summary>
    [StringLength(200)]
    public string? EventId { get; set; }

    /// <summary>
    ///     任务载荷。
    /// </summary>
    public JsonElement Payload { get; set; } = JsonDefaults.Object();

    public RefundNotificationCommand ToCommand(string provider)
    {
        return new RefundNotificationCommand(provider, RefundNo, ProviderRefundNo, Status, EventId, Payload);
    }
}

/// <summary>
///     更新积分兑换订单状态请求 DTO。
/// </summary>
public sealed class UpdatePointExchangeOrderStatusDto
{
    /// <summary>
    ///     订单 ID。
    /// </summary>
    [Required]
    public Guid OrderId { get; set; }

    /// <summary>
    ///     状态。
    /// </summary>
    public PointExchangeOrderStatus Status { get; set; }

    public UpdatePointExchangeOrderStatusCommand ToCommand()
    {
        return new UpdatePointExchangeOrderStatusCommand(OrderId, Status);
    }
}

/// <summary>
///     新增或更新租户优惠券请求 DTO。
/// </summary>
public sealed class UpsertTenantCouponDto
{
    /// <summary>
    ///     ID。
    /// </summary>
    public Guid? Id { get; set; }

    /// <summary>
    ///     编码。
    /// </summary>
    [Required]
    [StringLength(100)]
    public string Code { get; set; } = string.Empty;

    /// <summary>
    ///     套餐 ID。
    /// </summary>
    public Guid? PlanId { get; set; }

    /// <summary>
    ///     优惠类型。
    /// </summary>
    public DiscountType DiscountType { get; set; } = DiscountType.Fixed;

    /// <summary>
    ///     优惠值。
    /// </summary>
    [Range(typeof(decimal), "0.01", "999999")]
    public decimal DiscountValue { get; set; }

    /// <summary>
    ///     有效期开始时间。
    /// </summary>
    public DateTimeOffset? ValidFrom { get; set; }

    /// <summary>
    ///     有效期结束时间。
    /// </summary>
    public DateTimeOffset? ValidTo { get; set; }

    /// <summary>
    ///     最大使用次数。
    /// </summary>
    [Range(1, int.MaxValue)]
    public int? MaxUses { get; set; }

    /// <summary>
    ///     来源。
    /// </summary>
    [StringLength(50)]
    public string? Source { get; set; }

    /// <summary>
    ///     备注。
    /// </summary>
    [StringLength(1000)]
    public string? Remark { get; set; }

    public UpsertCouponCommand ToCommand()
    {
        return new UpsertCouponCommand(
            Id,
            Code,
            PlanId,
            DiscountType,
            DiscountValue,
            ValidFrom,
            ValidTo,
            MaxUses,
            Source,
            Remark);
    }
}