package storage

import (
	"time"

	"github.com/rs/zerolog/log"
	"gorm.io/gorm"

	"git.mstar.dev/mstar/linstrom/shared"
)

// MediaMetadata contains metadata about some media
// Metadata includes whether it's a remote file or not, what the name is,
// the MIME type, and an identifier pointing to its location
type MediaMetadata struct {
	ID        string    `gorm:"primarykey"` // The unique ID of this media file
	CreatedAt time.Time // When this entry was created
	UpdatedAt time.Time // When this entry was last updated
	// When this entry was deleted (for soft deletions)
	// Soft delete means that this entry still exists in the db, but gorm won't include it anymore unless specifically told to
	// If not null, this entry is marked as deleted
	DeletedAt gorm.DeletedAt `gorm:"index"`
	OwnedBy   string         // Account id this media belongs to
	Remote    bool           // whether the attachment is a remote one
	// Where the media is stored. Url
	Location string
	Type     string // What media type this is following mime types, eg image/png
	// Name of the file
	// Could be <emote-name>.png, <server-name>.webp for example. Or the name the file was uploaded with
	Name string
	// Alternative description of the media file's content
	AltText string
	// Whether the media is to be blurred by default
	Blurred bool
}

func (s *Storage) NewMediaMetadata(
	ownerId, location, mediaType, name string,
) (*MediaMetadata, error) {
	defer shared.Untrace(shared.Trace(&log.Logger))
	newMedia := MediaMetadata{
		OwnedBy:  ownerId,
		Location: location,
		Name:     name,
		Type:     mediaType,
	}
	s.db.Create(&newMedia)
	return nil, nil
}

func (s *Storage) FuzzyFindMediaMetadataByName(name string) ([]MediaMetadata, error) {
	defer shared.Untrace(shared.Trace(&log.Logger))
	notes := []MediaMetadata{}
	err := s.db.Where("name LIKE %?%", name).Find(notes).Error
	if err != nil {
		return nil, err
	}
	return notes, nil
}

func (s *Storage) GetMediaMetadataById(id string) (*MediaMetadata, error) {
	defer shared.Untrace(shared.Trace(&log.Logger))
	media := MediaMetadata{ID: id}
	err := s.db.First(&media).Error
	if err != nil {
		return nil, err
	}
	return &media, nil
}

func (s *Storage) FuzzyFindMediaMetadataByLocation(location string) ([]MediaMetadata, error) {
	defer shared.Untrace(shared.Trace(&log.Logger))
	data := []MediaMetadata{}
	if err := s.db.Where("location LIKE %?%", location).Find(data).Error; err != nil {
		return nil, err
	}
	return data, nil
}

func (s *Storage) DeleteMediaMetadataById(id string) error {
	defer shared.Untrace(shared.Trace(&log.Logger))
	return s.db.Delete(MediaMetadata{ID: id}).Error
}

func (s *Storage) DeleteMediaMetadataByFuzzyLocation(location string) error {
	defer shared.Untrace(shared.Trace(&log.Logger))
	var tmp MediaMetadata
	return s.db.Where("location LIKE %?%", location).Delete(&tmp).Error
}

func (s *Storage) DeleteMediaMetadataByFuzzyName(name string) error {
	defer shared.Untrace(shared.Trace(&log.Logger))
	var tmp MediaMetadata
	return s.db.Where("name LIKE %?%", name).Delete(&tmp).Error
}
