namespace Tiku.Application.Storage;

public static class ObjectStorageProviders
{
    public const string ExternalUrl = "external_url";
    public const string AliyunOss = "aliyun_oss";
    public const string TencentCos = "tencent_cos";
    public const string QiniuKodo = "qiniu_kodo";
    public const string LocalDev = "local_dev";
}

public sealed record StorageAssetLocation(
    string Provider,
    string? Bucket,
    string? ObjectKey,
    string? CdnUrl = null);

public sealed record ObjectStorageUploadSignRequest(
    Guid TenantId,
    string Provider,
    string Bucket,
    string ObjectKey,
    string FileName,
    string MimeType,
    long? FileSizeBytes,
    TimeSpan ExpiresIn,
    bool Upsert = false);

public sealed record ObjectStorageDownloadSignRequest(
    Guid TenantId,
    string Provider,
    string? Bucket,
    string? ObjectKey,
    TimeSpan ExpiresIn,
    string? CdnUrl = null,
    string? FileName = null,
    string Disposition = "attachment");

public sealed record ObjectStorageHeadRequest(
    Guid TenantId,
    string Provider,
    string? Bucket,
    string? ObjectKey,
    string? DeclaredMimeType = null,
    long? DeclaredFileSizeBytes = null,
    string? DeclaredChecksumSha256 = null);

public sealed record ObjectStorageReadRequest(
    Guid TenantId,
    string Provider,
    string Bucket,
    string ObjectKey);

public sealed record ObjectStorageWriteRequest(
    Guid TenantId,
    string Provider,
    string Bucket,
    string ObjectKey,
    string MimeType,
    Stream Content,
    long? FileSizeBytes,
    string? ChecksumSha256 = null,
    IReadOnlyDictionary<string, string>? Metadata = null,
    bool Upsert = true);

public sealed record ObjectStorageSignedUrl(
    string Provider,
    string? Bucket,
    string? ObjectKey,
    string Method,
    Uri Url,
    IReadOnlyDictionary<string, string> Headers,
    DateTimeOffset ExpiresAt,
    TimeSpan ExpiresIn,
    string SignatureMode);

public sealed record ObjectStorageMetadata(
    string Provider,
    string? Bucket,
    string? ObjectKey,
    bool Exists,
    long? SizeBytes,
    string? MimeType,
    string? ChecksumSha256,
    string? ETag,
    string? LastModified,
    IReadOnlyDictionary<string, string> RawHeaders,
    string VerificationSource);

public sealed record ObjectStorageWriteResult(
    string Provider,
    string Bucket,
    string ObjectKey,
    Uri? PublicUrl,
    long? SizeBytes,
    string? MimeType,
    string? ChecksumSha256,
    string? ETag,
    IReadOnlyDictionary<string, string> RawHeaders,
    string VerificationSource);

public class ObjectStorageException(string message, string code) : InvalidOperationException(message)
{
    public string Code { get; } = code;
}

public sealed class ObjectStorageNotConfiguredException(string message)
    : ObjectStorageException(message, "STORAGE_PROVIDER_NOT_CONFIGURED");