using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using NodaTime;

namespace DysonNetwork.Sphere.Storage;

public class RemoteStorageConfig
{
    public string Id { get; set; } = string.Empty;
    public string Label { get; set; } = string.Empty;
    public string Region { get; set; } = string.Empty;
    public string Bucket { get; set; } = string.Empty;
    public string Endpoint { get; set; } = string.Empty;
    public string SecretId { get; set; } = string.Empty;
    public string SecretKey { get; set; } = string.Empty;
    public bool EnableSigned { get; set; }
    public bool EnableSsl { get; set; }
    public string? ImageProxy { get; set; }
    public string? AccessProxy { get; set; }
}

/// <summary>
/// The class that used in jsonb columns which referenced the cloud file.
/// The aim of this class is to store some properties that won't change to a file to reduce the database load.
/// </summary>
public class CloudFileReferenceObject : ModelBase, ICloudFile
{
    public string Id { get; set; } = null!;
    public string Name { get; set; } = string.Empty;
    public Dictionary<string, object>? FileMeta { get; set; } = null!;
    public Dictionary<string, object>? UserMeta { get; set; } = null!;
    public string? MimeType { get; set; }
    public string? Hash { get; set; }
    public long Size { get; set; }
    public bool HasCompression { get; set; } = false;
}

public class CloudFile : ModelBase, ICloudFile, IIdentifiedResource
{
    /// The id generated by TuS, basically just UUID remove the dash lines
    [MaxLength(32)]
    public string Id { get; set; } = Guid.NewGuid().ToString();

    [MaxLength(1024)] public string Name { get; set; } = string.Empty;
    [MaxLength(4096)] public string? Description { get; set; }
    [Column(TypeName = "jsonb")] public Dictionary<string, object>? FileMeta { get; set; } = null!;
    [Column(TypeName = "jsonb")] public Dictionary<string, object>? UserMeta { get; set; } = null!;
    [Column(TypeName = "jsonb")] public List<CloudFileSensitiveMark>? SensitiveMarks { get; set; } = [];
    [MaxLength(256)] public string? MimeType { get; set; }
    [MaxLength(256)] public string? Hash { get; set; }
    public long Size { get; set; }
    public Instant? UploadedAt { get; set; }
    [MaxLength(128)] public string? UploadedTo { get; set; }
    public bool HasCompression { get; set; } = false;

    /// The object name which stored remotely,
    /// multiple cloud file may have same storage id to indicate they are the same file
    /// 
    /// If the storage id was null and the uploaded at is not null, means it is an embedding file,
    /// The embedding file means the file is store on another site,
    /// or it is a webpage (based on mimetype)
    [MaxLength(32)]
    public string? StorageId { get; set; }

    /// This field should be null when the storage id is filled
    /// Indicates the off-site accessible url of the file
    [MaxLength(4096)]
    public string? StorageUrl { get; set; }

    [JsonIgnore] public Account.Account Account { get; set; } = null!;
    public Guid AccountId { get; set; }

    public CloudFileReferenceObject ToReferenceObject()
    {
        return new CloudFileReferenceObject
        {
            CreatedAt = CreatedAt,
            UpdatedAt = UpdatedAt,
            DeletedAt = DeletedAt,
            Id = Id,
            Name = Name,
            FileMeta = FileMeta,
            UserMeta = UserMeta,
            MimeType = MimeType,
            Hash = Hash,
            Size = Size,
            HasCompression = HasCompression
        };
    }

    public string ResourceIdentifier => $"file/{Id}";
}

public enum CloudFileSensitiveMark
{
    Language,
    SexualContent,
    Violence,
    Profanity,
    HateSpeech,
    Racism,
    AdultContent,
    DrugAbuse,
    AlcoholAbuse,
    Gambling,
    SelfHarm,
    ChildAbuse,
    Other
}

public class CloudFileReference : ModelBase
{
    public Guid Id { get; set; } = Guid.NewGuid();
    [MaxLength(32)] public string FileId { get; set; } = null!;
    public CloudFile File { get; set; } = null!;
    [MaxLength(1024)] public string Usage { get; set; } = null!;
    [MaxLength(1024)] public string ResourceId { get; set; } = null!;

    /// <summary>
    /// Optional expiration date for the file reference
    /// </summary>
    public Instant? ExpiredAt { get; set; }
}