using System.Text.Json;
using Tiku.Application.Catalog;
using Tiku.Application.Storage;
using Tiku.Domain.Content;

namespace Tiku.Application.Assets;

public sealed record AssetManagementActor(Guid TenantId, Guid UserId);

public sealed record AssetUploadSignCommand(
    Guid? AssetId,
    Guid? RegionId,
    Guid? SubjectId,
    Guid? CategoryId,
    Guid? ContentNodeId,
    string? AssetKey,
    string? Title,
    string? Category,
    string? Description,
    string FileName,
    string MimeType,
    long? FileSizeBytes,
    string? ChecksumSha256,
    string? AssetType,
    string? Visibility,
    bool? IsPublic,
    string? Provider,
    string? Bucket,
    string? ObjectKey,
    int? ExpiresInSeconds,
    JsonElement Metadata);

public sealed record AssetUploadConfirmCommand(
    Guid AssetId,
    string? MimeType,
    long? FileSizeBytes,
    string? ChecksumSha256);

public sealed record UpsertAssetCommand(
    Guid? AssetId,
    Guid? RegionId,
    Guid? SubjectId,
    Guid? CategoryId,
    Guid? ContentNodeId,
    string? LegacyId,
    string? AssetKey,
    string? Title,
    string? Category,
    string? Description,
    string? FileName,
    string? CdnUrl,
    bool? IsPublic,
    string? AssetType,
    string? Visibility,
    string? Status,
    string? Provider,
    string? Bucket,
    string? ObjectKey,
    string? MimeType,
    long? FileSizeBytes,
    string? ChecksumSha256,
    string? PreviewUrl,
    string? PreviewObjectKey,
    int? Order,
    JsonElement AccessRules,
    JsonElement Metadata);

public sealed record AssetAccessSignCommand(Guid AssetId, int? ExpiresInSeconds);

public sealed record AssetManagementFilter(
    Guid? RegionId = null,
    Guid? SubjectId = null,
    Guid? CategoryId = null,
    Guid? ContentNodeId = null,
    string? AssetType = null,
    string? Category = null,
    string? UploadStatus = null,
    string? SecurityScanStatus = null,
    string? Keyword = null,
    int? Limit = null);

public sealed record ImportJobFilter(
    string? Status = null,
    string? ImportType = null,
    string? SourceFormat = null,
    int? Limit = null);

public sealed record AssetEventFilter(Guid? AssetId = null, Guid? UserId = null, int? Limit = null);

public sealed record ContentAssetManagementItem(
    Guid Id,
    string? LegacyId,
    Guid? RegionId,
    Guid? SubjectId,
    Guid? CategoryId,
    Guid? ContentNodeId,
    string? AssetKey,
    string? Title,
    string? Category,
    string? Description,
    string? FileName,
    string? CdnUrl,
    bool IsPublic,
    ContentAssetType AssetType,
    AssetStorageProvider StorageProvider,
    string? Bucket,
    string? ObjectKey,
    string? MimeType,
    long? FileSizeBytes,
    string? ChecksumSha256,
    ContentVisibility Visibility,
    ContentStatus Status,
    int Order,
    AssetUploadStatus UploadStatus,
    DateTimeOffset? VerifiedAt,
    long? VerifiedSizeBytes,
    string? VerifiedChecksumSha256,
    AssetPreviewStatus PreviewStatus,
    AssetSecurityScanStatus SecurityScanStatus,
    JsonElement Metadata,
    DateTimeOffset CreatedAt,
    DateTimeOffset? UpdatedAt);

public sealed record AssetUploadSignResult(
    ContentAssetManagementItem Item,
    ObjectStorageSignedUrl Upload);

public sealed record AssetUploadConfirmResult(
    ContentAssetManagementItem Item,
    ObjectStorageMetadata Metadata);

public sealed record AssetManagementSignedAccessResult(
    ContentAssetManagementItem Item,
    ObjectStorageSignedUrl Url);

public sealed record ContentAssetAccessEventItem(
    Guid Id,
    Guid? AssetId,
    Guid? UserId,
    AssetAccessActorRole ActorRole,
    AssetAccessType AccessType,
    string? Visibility,
    string? AssetType,
    string? StorageProvider,
    AssetAccessDisposition? Disposition,
    int? ExpiresInSeconds,
    string? SignatureMode,
    AssetAccessResult Result,
    string? DenyCode,
    string? IpAddress,
    string? UserAgent,
    JsonElement Metadata,
    DateTimeOffset CreatedAt);

public sealed record ContentAssetSecurityScanEventItem(
    Guid Id,
    Guid? AssetId,
    string Provider,
    AssetSecurityScanStatus ScanStatus,
    AssetSecurityRiskLevel RiskLevel,
    string[] IssueCodes,
    JsonElement Details,
    DateTimeOffset CreatedAt);

public sealed record ContentImportJobItem(
    Guid Id,
    Guid? TargetRegionId,
    Guid? TargetSubjectId,
    Guid? TargetCategoryId,
    Guid? TargetContentNodeId,
    Guid? TargetQuestionBankId,
    ContentImportType ImportType,
    ImportSourceFormat SourceFormat,
    ContentImportStatus Status,
    string? SourceName,
    string? SourceHash,
    bool DryRun,
    int TotalCount,
    int ValidCount,
    int ErrorCount,
    int WarningCount,
    int InsertedCount,
    int UpdatedCount,
    int SkippedCount,
    JsonElement Summary,
    string? ErrorMessage,
    DateTimeOffset? StartedAt,
    DateTimeOffset? FinishedAt,
    DateTimeOffset CreatedAt,
    DateTimeOffset? UpdatedAt);

public sealed record ContentImportItemModel(
    Guid Id,
    Guid JobId,
    int RowNo,
    string? ExternalId,
    ContentImportItemStatus Status,
    string? TargetType,
    Guid? TargetId,
    JsonElement SourcePayload,
    JsonElement NormalizedPayload,
    string? ContentHash,
    int IssuesCount);

public sealed record ContentImportIssueModel(
    Guid Id,
    Guid JobId,
    Guid? ItemId,
    int? RowNo,
    ImportIssueSeverity Severity,
    string Code,
    string? FieldPath,
    string Message,
    JsonElement Details);

public sealed record ContentImportJobDetail(
    ContentImportJobItem Job,
    IReadOnlyCollection<ContentImportItemModel> Items,
    IReadOnlyCollection<ContentImportIssueModel> Issues);

public sealed class AssetManagementException(string message, string code) : Exception(message)
{
    public string Code { get; } = code;
}
