package goscrobble

import (
	"database/sql"
	"errors"
	"log"
	"net"
	"time"
)

type JellyfinRequest struct {
	Album                           string `json:"Album"`
	Artist                          string `json:"Artist"`
	ClientName                      string `json:"ClientName"`
	DeviceID                        string `json:"DeviceId"`
	DeviceName                      string `json:"DeviceName"`
	IsAutomated                     bool   `json:"IsAutomated"`
	IsPaused                        bool   `json:"IsPaused"`
	ItemID                          string `json:"ItemId"`
	ItemType                        string `json:"ItemType"`
	MediaSourceID                   string `json:"MediaSourceId"`
	Name                            string `json:"Name"`
	NotificationType                string `json:"NotificationType"`
	Overview                        string `json:"Overview"`
	PlaybackPosition                string `json:"PlaybackPosition"`
	PlaybackPositionTicks           int64  `json:"PlaybackPositionTicks"`
	ProviderMusicbrainzalbum        string `json:"Provider_musicbrainzalbum"`
	ProviderMusicbrainzalbumartist  string `json:"Provider_musicbrainzalbumartist"`
	ProviderMusicbrainzartist       string `json:"Provider_musicbrainzartist"`
	ProviderMusicbrainzreleasegroup string `json:"Provider_musicbrainzreleasegroup"`
	ProviderMusicbrainztrack        string `json:"Provider_musicbrainztrack"`
	RunTime                         string `json:"RunTime"`
	RunTimeTicks                    int64  `json:"RunTimeTicks"`
	ServerID                        string `json:"ServerId"`
	ServerName                      string `json:"ServerName"`
	ServerURL                       string `json:"ServerUrl"`
	ServerVersion                   string `json:"ServerVersion"`
	Timestamp                       string `json:"Timestamp"`
	UserID                          string `json:"UserId"`
	Username                        string `json:"Username"`
	UtcTimestamp                    string `json:"UtcTimestamp"`
	Year                            int64  `json:"Year"`
}

// ParseJellyfinInput - Transform API data into a common struct. Uses MusicBrainzID primarily
func ParseJellyfinInput(userUUID string, jf JellyfinRequest, ip net.IP, tx *sql.Tx) error {
	// Debugging
	// fmt.Printf("%+v", jf)

	// Prevents scrobbling same song twice!
	cacheKey := jf.UserID + ":" + jf.Name + ":" + jf.Artist + ":" + jf.Album + ":" + jf.ServerID
	redisKey := getMd5(cacheKey + userUUID)
	if getRedisKeyExists(redisKey) {
		return nil
	}

	if jf.ItemType != "Audio" {
		return errors.New("Media type not audio")
	}

	// Safety Checks
	if jf.Artist == "" {
		return errors.New("Missing artist data")
	}

	if jf.Album == "" {
		return errors.New("Missing album data")
	}

	if jf.Name == "" {
		return errors.New("Missing track data")
	}

	// Insert artist if not exist
	artist, err := insertArtist(jf.Artist, jf.ProviderMusicbrainzartist, "", "", tx)
	if err != nil {
		log.Printf("%+v", err)
		return errors.New("Failed to map artist")
	}

	// Insert album if not exist
	artists := []string{artist.UUID}
	album, err := insertAlbum(jf.Album, jf.ProviderMusicbrainzalbum, "", artists, "", tx)
	if err != nil {
		log.Printf("%+v", err)
		return errors.New("Failed to map album")
	}

	// Insert track if not exist
	length := timestampToSeconds(jf.RunTime)
	track, err := insertTrack(jf.Name, length, jf.ProviderMusicbrainztrack, "", album.UUID, artists, tx)
	if err != nil {
		log.Printf("%+v", err)
		return errors.New("Failed to map track")
	}

	// Insert scrobble if not exist
	timestamp := time.Now()
	err = insertScrobble(userUUID, track.UUID, "jellyfin", timestamp, ip, tx)
	if err != nil {
		log.Printf("%+v", err)
		return errors.New("Failed to map track")
	}

	// Add cache key!
	ttl := time.Duration(timestampToSeconds(jf.RunTime)) * time.Second
	setRedisValTtl(redisKey, "1", ttl)

	return nil
}
