using Butter.Types;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Lactose.Models;

/// <summary>
/// Represents an asset in the system.
/// </summary>
[Index(nameof(OriginalPath), IsUnique = true)]
public class Asset {
    /// <summary>
    /// Gets or sets the unique identifier for the asset.
    /// </summary>
    [Key]
    public Guid Id { get; set; }

    /// <summary>
    /// Gets or sets the original path of the asset.
    /// </summary>
    [Column(TypeName = "VARCHAR(2048)")]
    public required string OriginalPath { get; set; } = string.Empty;

    /// <summary>
    /// Gets or sets the original filename of the asset.
    /// </summary>
    /// <remarks>
    /// This is needed to preserve the original filename when the asset is uploaded from the web as it would be renamed to avoid filename collisions.
    /// </remarks>
    [Column(TypeName = "VARCHAR(255)")]
    public required string OriginalFilename { get; set; } = string.Empty;

    /// <summary>
    /// Gets or sets the thumbnail path of the asset.
    /// </summary>
    [Column(TypeName = "VARCHAR(2048)")]
    public string ThumbnailPath { get; set; } = string.Empty;

    /// <summary>
    /// Gets or sets the preview path of the asset.
    /// </summary>
    [Column(TypeName = "VARCHAR(2048)")]
    public string PreviewPath { get; set; } = string.Empty;

    /// <summary>
    /// Gets or sets the type of the asset.
    /// </summary>
    public required EAssetType Type { get; set; }

    /// <summary>
    /// Gets or sets the owner ID of the asset.
    /// </summary>
    [ForeignKey(nameof(Owner))]
    public Guid? OwnerId { get; set; }

    /// <summary>
    /// Gets or sets a value indicating whether the asset is publicly shared.
    /// </summary>
    public bool IsPubliclyShared { get; set; }

    /// <summary>
    /// Gets or sets the creation date of the asset.
    /// </summary>
    [Required]
    public required DateTime CreatedAt { get; set; } = DateTime.Now;

    /// <summary>
    /// Gets or sets the last updated date of the asset.
    /// </summary>
    public DateTime? UpdatedAt { get; set; }

    /// <summary>
    /// Gets or sets the deletion date of the asset.
    /// </summary>
    public DateTime? DeletedAt { get; set; }

    /// <summary>
    /// Gets or sets the MIME type of the asset.
    /// </summary>
    [Required][Column(TypeName = "VARCHAR(255)")]
    public string MimeType { get; set; } = string.Empty;

    /// <summary>
    /// Gets or sets the resolution width of the asset.
    /// </summary>
    public int ResolutionWidth { get; set; }

    /// <summary>
    /// Gets or sets the resolution height of the asset.
    /// </summary>
    public int ResolutionHeight { get; set; }

    /// <summary>
    /// Gets or sets the file size of the asset.
    /// </summary>
    public long FileSize { get; set; }

    /// <summary>
    /// Gets or sets the duration of the asset.
    /// </summary>
    public float? Duration { get; set; }

    /// <summary>
    /// Gets or sets the frame rate of the asset.
    /// </summary>
    public float? FrameRate { get; set; }

    /// <summary>
    /// Computed hash of the asset.
    /// </summary>
    [Required][Column(TypeName = "BYTEA")]
    public byte[] Hash { get; set; } = [];

    /// <summary>
    /// Gets or Sets which folder the asset is in.
    /// </summary>
    [ForeignKey(nameof(Folder))]
    public Guid? FolderId { get; set; }

#region Navigation Properties

    /// <summary>
    /// Gets or sets the owner of the asset.
    /// </summary>
    public User? Owner { get; set; }

    /// <summary>
    /// Gets or sets the list of users with whom the asset is shared.
    /// </summary>
    public List<User>? SharedWith { get; set; }

    /// <summary>
    /// Gets or sets the list of albums associated with the asset.
    /// </summary>
    public List<Album>? Albums { get; set; }

    /// <summary>
    /// Gets or sets the list of tags associated with the asset.
    /// </summary>
    public List<Tag>? Tags { get; set; }

    /// <summary>
    /// Gets or sets the list of faces detected in the asset.
    /// </summary>
    public List<Face>? Faces { get; set; }

    /// <summary>
    /// Gets or sets the folder containing the asset.
    /// </summary>
    public Folder? Folder { get; set; }

#endregion
}
