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

namespace Tiku.Api.Contracts;

/// <summary>
/// 创建资产上传签名请求。
/// </summary>
public sealed class AssetUploadSignDto
{
    /// <summary>
    /// 资产 ID。
    /// </summary>
    public Guid? AssetId { get; set; }

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

    /// <summary>
    /// 科目 ID。
    /// </summary>
    public Guid? SubjectId { get; set; }

    /// <summary>
    /// 分类 ID。
    /// </summary>
    public Guid? CategoryId { get; set; }

    /// <summary>
    /// 内容节点 ID。
    /// </summary>
    public Guid? ContentNodeId { get; set; }

    /// <summary>
    /// 资产键。
    /// </summary>
    [StringLength(200)]
    public string? AssetKey { get; set; }

    /// <summary>
    /// 标题。
    /// </summary>
    [StringLength(300)]
    public string? Title { get; set; }

    /// <summary>
    /// 分类。
    /// </summary>
    [StringLength(100)]
    public string? Category { get; set; }

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

    /// <summary>
    /// 文件名。
    /// </summary>
    [Required]
    [StringLength(500)]
    public string FileName { get; set; } = string.Empty;

    /// <summary>
    /// MIME 类型。
    /// </summary>
    [Required]
    [StringLength(200)]
    public string MimeType { get; set; } = string.Empty;

    /// <summary>
    /// 文件大小，单位为字节。
    /// </summary>
    [Range(0, long.MaxValue)]
    public long? FileSizeBytes { get; set; }

    /// <summary>
    /// SHA-256 校验值。
    /// </summary>
    [RegularExpression("^[A-Fa-f0-9]{64}$")]
    public string? ChecksumSha256 { get; set; }

    /// <summary>
    /// 资产类型。
    /// </summary>
    [StringLength(50)]
    public string? AssetType { get; set; }

    /// <summary>
    /// 可见性。
    /// </summary>
    [StringLength(50)]
    public string? Visibility { get; set; }

    /// <summary>
    /// 是否公开。
    /// </summary>
    public bool? IsPublic { get; set; }

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

    /// <summary>
    /// 存储桶。
    /// </summary>
    [StringLength(200)]
    public string? Bucket { get; set; }

    /// <summary>
    /// 对象存储键。
    /// </summary>
    [StringLength(1000)]
    public string? ObjectKey { get; set; }

    /// <summary>
    /// 有效期秒数。
    /// </summary>
    [Range(1, 3600)]
    public int? ExpiresInSeconds { get; set; }

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

    public AssetUploadSignCommand ToCommand()
    {
        return new AssetUploadSignCommand(
            AssetId,
            RegionId,
            SubjectId,
            CategoryId,
            ContentNodeId,
            AssetKey,
            Title,
            Category,
            Description,
            FileName,
            MimeType,
            FileSizeBytes,
            ChecksumSha256,
            AssetType,
            Visibility,
            IsPublic,
            Provider,
            Bucket,
            ObjectKey,
            ExpiresInSeconds,
            Metadata);
    }
}

/// <summary>
/// 确认资产上传请求。
/// </summary>
public sealed class AssetUploadConfirmDto
{
    /// <summary>
    /// 资产 ID。
    /// </summary>
    [Required]
    public Guid AssetId { get; set; }

    /// <summary>
    /// MIME 类型。
    /// </summary>
    [StringLength(200)]
    public string? MimeType { get; set; }

    /// <summary>
    /// 文件大小，单位为字节。
    /// </summary>
    [Range(0, long.MaxValue)]
    public long? FileSizeBytes { get; set; }

    /// <summary>
    /// SHA-256 校验值。
    /// </summary>
    [RegularExpression("^[A-Fa-f0-9]{64}$")]
    public string? ChecksumSha256 { get; set; }

    public AssetUploadConfirmCommand ToCommand()
    {
        return new AssetUploadConfirmCommand(AssetId, MimeType, FileSizeBytes, ChecksumSha256);
    }
}

/// <summary>
/// 新增或更新内容资产请求。
/// </summary>
public sealed class UpsertAssetDto
{
    /// <summary>
    /// 资产 ID。
    /// </summary>
    public Guid? AssetId { get; set; }
    /// <summary>
    /// 地区 ID。
    /// </summary>
    public Guid? RegionId { get; set; }
    /// <summary>
    /// 科目 ID。
    /// </summary>
    public Guid? SubjectId { get; set; }
    /// <summary>
    /// 分类 ID。
    /// </summary>
    public Guid? CategoryId { get; set; }
    /// <summary>
    /// 内容节点 ID。
    /// </summary>
    public Guid? ContentNodeId { get; set; }
    /// <summary>
    /// 历史系统 ID。
    /// </summary>
    public string? LegacyId { get; set; }
    /// <summary>
    /// 资产键。
    /// </summary>
    public string? AssetKey { get; set; }
    /// <summary>
    /// 标题。
    /// </summary>
    public string? Title { get; set; }
    /// <summary>
    /// 分类。
    /// </summary>
    public string? Category { get; set; }
    /// <summary>
    /// 说明。
    /// </summary>
    public string? Description { get; set; }
    /// <summary>
    /// 文件名。
    /// </summary>
    public string? FileName { get; set; }
    /// <summary>
    /// CDN 地址。
    /// </summary>
    public string? CdnUrl { get; set; }
    /// <summary>
    /// 是否公开。
    /// </summary>
    public bool? IsPublic { get; set; }
    /// <summary>
    /// 资产类型。
    /// </summary>
    public string? AssetType { get; set; }
    /// <summary>
    /// 可见性。
    /// </summary>
    public string? Visibility { get; set; }
    /// <summary>
    /// 状态。
    /// </summary>
    public string? Status { get; set; }
    /// <summary>
    /// 服务提供方。
    /// </summary>
    public string? Provider { get; set; }
    /// <summary>
    /// 存储桶。
    /// </summary>
    public string? Bucket { get; set; }
    /// <summary>
    /// 对象存储键。
    /// </summary>
    public string? ObjectKey { get; set; }
    /// <summary>
    /// MIME 类型。
    /// </summary>
    public string? MimeType { get; set; }
    /// <summary>
    /// 文件大小，单位为字节。
    /// </summary>
    public long? FileSizeBytes { get; set; }
    /// <summary>
    /// SHA-256 校验值。
    /// </summary>
    public string? ChecksumSha256 { get; set; }
    /// <summary>
    /// 预览地址。
    /// </summary>
    public string? PreviewUrl { get; set; }
    /// <summary>
    /// 预览对象存储键。
    /// </summary>
    public string? PreviewObjectKey { get; set; }
    /// <summary>
    /// 显示顺序。
    /// </summary>
    public int? Order { get; set; }
    /// <summary>
    /// 访问规则。
    /// </summary>
    public JsonElement AccessRules { get; set; } = JsonDefaults.Object();
    /// <summary>
    /// 扩展元数据。
    /// </summary>
    public JsonElement Metadata { get; set; } = JsonDefaults.Object();

    public UpsertAssetCommand ToCommand()
    {
        return new UpsertAssetCommand(
            AssetId,
            RegionId,
            SubjectId,
            CategoryId,
            ContentNodeId,
            LegacyId,
            AssetKey,
            Title,
            Category,
            Description,
            FileName,
            CdnUrl,
            IsPublic,
            AssetType,
            Visibility,
            Status,
            Provider,
            Bucket,
            ObjectKey,
            MimeType,
            FileSizeBytes,
            ChecksumSha256,
            PreviewUrl,
            PreviewObjectKey,
            Order,
            AccessRules,
            Metadata);
    }
}

/// <summary>
/// 创建资产访问签名请求。
/// </summary>
public sealed class AssetAccessSignDto
{
    /// <summary>
    /// 资产 ID。
    /// </summary>
    [Required]
    public Guid AssetId { get; set; }

    /// <summary>
    /// 有效期秒数。
    /// </summary>
    [Range(60, 3600)]
    public int? ExpiresInSeconds { get; set; }

    public AssetAccessSignCommand ToCommand()
    {
        return new AssetAccessSignCommand(AssetId, ExpiresInSeconds);
    }
}

/// <summary>
/// 资产管理查询参数。
/// </summary>
public sealed class AssetManagementQueryDto
{
    /// <summary>
    /// 地区 ID。
    /// </summary>
    public Guid? RegionId { get; set; }

    /// <summary>
    /// 科目 ID。
    /// </summary>
    public Guid? SubjectId { get; set; }

    /// <summary>
    /// 分类 ID。
    /// </summary>
    public Guid? CategoryId { get; set; }

    /// <summary>
    /// 内容节点 ID。
    /// </summary>
    public Guid? ContentNodeId { get; set; }

    /// <summary>
    /// 资产类型。
    /// </summary>
    [StringLength(50)]
    public string? AssetType { get; set; }

    /// <summary>
    /// 分类。
    /// </summary>
    [StringLength(100)]
    public string? Category { get; set; }

    /// <summary>
    /// 上传状态。
    /// </summary>
    [StringLength(50)]
    public string? UploadStatus { get; set; }

    /// <summary>
    /// 安全扫描状态。
    /// </summary>
    [StringLength(50)]
    public string? SecurityScanStatus { get; set; }

    /// <summary>
    /// 关键字。
    /// </summary>
    [StringLength(100)]
    public string? Keyword { get; set; }

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

    public AssetManagementFilter ToFilter()
    {
        return new AssetManagementFilter(
            RegionId,
            SubjectId,
            CategoryId,
            ContentNodeId,
            AssetType,
            Category,
            UploadStatus,
            SecurityScanStatus,
            Keyword,
            Limit);
    }
}

/// <summary>
/// 资产事件查询参数。
/// </summary>
public sealed class AssetEventQueryDto
{
    /// <summary>
    /// 资产 ID。
    /// </summary>
    public Guid? AssetId { get; set; }
    /// <summary>
    /// 用户 ID。
    /// </summary>
    public Guid? UserId { get; set; }

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

    public AssetEventFilter ToFilter()
    {
        return new AssetEventFilter(AssetId, UserId, Limit);
    }
}

/// <summary>
/// 导入任务查询参数。
/// </summary>
public sealed class ImportJobQueryDto
{
    /// <summary>
    /// 状态。
    /// </summary>
    [StringLength(50)]
    public string? Status { get; set; }

    /// <summary>
    /// 导入Type。
    /// </summary>
    [StringLength(50)]
    public string? ImportType { get; set; }

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

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

    public ImportJobFilter ToFilter()
    {
        return new ImportJobFilter(Status, ImportType, SourceFormat, Limit);
    }
}
