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

namespace Tiku.Api.Contracts;

public sealed class AssetUploadSignDto
{
    public Guid? AssetId { get; set; }

    public Guid? RegionId { get; set; }

    public Guid? SubjectId { get; set; }

    public Guid? CategoryId { get; set; }

    public Guid? ContentNodeId { get; set; }

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

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

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

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

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

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

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

    [RegularExpression("^[A-Fa-f0-9]{64}$")]
    public string? ChecksumSha256 { get; set; }

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

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

    public bool? IsPublic { get; set; }

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

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

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

    [Range(1, 3600)]
    public int? ExpiresInSeconds { get; set; }

    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);
    }
}

public sealed class AssetUploadConfirmDto
{
    [Required]
    public Guid AssetId { get; set; }

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

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

    [RegularExpression("^[A-Fa-f0-9]{64}$")]
    public string? ChecksumSha256 { get; set; }

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

public sealed class UpsertAssetDto
{
    public Guid? AssetId { get; set; }
    public Guid? RegionId { get; set; }
    public Guid? SubjectId { get; set; }
    public Guid? CategoryId { get; set; }
    public Guid? ContentNodeId { get; set; }
    public string? LegacyId { get; set; }
    public string? AssetKey { get; set; }
    public string? Title { get; set; }
    public string? Category { get; set; }
    public string? Description { get; set; }
    public string? FileName { get; set; }
    public string? CdnUrl { get; set; }
    public bool? IsPublic { get; set; }
    public string? AssetType { get; set; }
    public string? Visibility { get; set; }
    public string? Status { get; set; }
    public string? Provider { get; set; }
    public string? Bucket { get; set; }
    public string? ObjectKey { get; set; }
    public string? MimeType { get; set; }
    public long? FileSizeBytes { get; set; }
    public string? ChecksumSha256 { get; set; }
    public string? PreviewUrl { get; set; }
    public string? PreviewObjectKey { get; set; }
    public int? Order { get; set; }
    public JsonElement AccessRules { get; set; } = JsonDefaults.Object();
    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);
    }
}

public sealed class AssetAccessSignDto
{
    [Required]
    public Guid AssetId { get; set; }

    [Range(60, 3600)]
    public int? ExpiresInSeconds { get; set; }

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

public sealed class AssetManagementQueryDto
{
    public Guid? RegionId { get; set; }

    public Guid? SubjectId { get; set; }

    public Guid? CategoryId { get; set; }

    public Guid? ContentNodeId { get; set; }

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

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

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

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

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

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

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

public sealed class AssetEventQueryDto
{
    public Guid? AssetId { get; set; }
    public Guid? UserId { get; set; }

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

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

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

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

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

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

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