/*
Copyright © 2024 Philipp Wolfer <phw@uploadedlobster.com>

Scotty is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later version.

Scotty is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
Scotty. If not, see <https://www.gnu.org/licenses/>.
*/

package spotifyhistory

import (
	"encoding/json"
	"fmt"
	"io"
	"strings"
	"time"

	"go.uploadedlobster.com/scotty/internal/models"
)

type StreamingHistory []HistoryItem

type ListenListOptions struct {
	IgnoreIncognito   bool
	IgnoreSkipped     bool
	skippedMinSeconds int
}

type HistoryItem struct {
	Timestamp                     time.Time `json:"ts"`
	UserName                      string    `json:"username"`
	Platform                      string    `json:"platform"`
	MillisecondsPlayed            int       `json:"ms_played"`
	ConnCountry                   string    `json:"conn_country"`
	IpAddrDecrypted               string    `json:"ip_addr_decrypted"`
	UserAgentDecrypted            string    `json:"user_agent_decrypted"`
	MasterMetadataTrackName       string    `json:"master_metadata_track_name"`
	MasterMetadataAlbumArtistName string    `json:"master_metadata_album_artist_name"`
	MasterMetadataAlbumName       string    `json:"master_metadata_album_album_name"`
	SpotifyTrackUri               string    `json:"spotify_track_uri"`
	EpisodeName                   string    `json:"episode_name"`
	EpisodeShowName               string    `json:"episode_show_name"`
	SpotifyEpisodeUri             string    `json:"spotify_episode_uri"`
	ReasonStart                   string    `json:"reason_start"`
	ReasonEnd                     string    `json:"reason_end"`
	Shuffle                       bool      `json:"shuffle"`
	Skipped                       bool      `json:"skipped"`
	Offline                       bool      `json:"offline"`
	OfflineTimestamp              int       `json:"offline_timestamp"`
	IncognitoMode                 bool      `json:"incognito_mode"`
}

func (j *StreamingHistory) Read(in io.Reader) error {
	bytes, err := io.ReadAll(in)
	if err != nil {
		return err
	}
	err = json.Unmarshal(bytes, j)
	return err
}

func (h *StreamingHistory) AsListenList(opt ListenListOptions) models.ListensList {
	listens := make(models.ListensList, 0, len(*h))
	for _, item := range *h {
		if item.MasterMetadataTrackName == "" ||
			(opt.IgnoreIncognito && item.IncognitoMode) ||
			(opt.IgnoreSkipped && item.Skipped) ||
			(item.Skipped && item.MillisecondsPlayed < opt.skippedMinSeconds*1000) {
			continue
		}
		listens = append(listens, item.AsListen())
	}
	return listens
}

func (i HistoryItem) AsListen() models.Listen {
	listen := models.Listen{
		Track: models.Track{
			TrackName:      i.MasterMetadataTrackName,
			ReleaseName:    i.MasterMetadataAlbumName,
			ArtistNames:    []string{i.MasterMetadataAlbumArtistName},
			AdditionalInfo: models.AdditionalInfo{},
		},
		ListenedAt:       i.Timestamp,
		PlaybackDuration: time.Duration(i.MillisecondsPlayed * int(time.Millisecond)),
		UserName:         i.UserName,
	}
	if trackURL, err := formatSpotifyUri(i.SpotifyTrackUri); err != nil {
		listen.AdditionalInfo["spotify_id"] = trackURL
	}
	return listen
}

// Returns a Spotify ID like "spotify:track:5jzma6gCzYtKB1DbEwFZKH" into an
// URL like "https://open.spotify.com/track/5jzma6gCzYtKB1DbEwFZKH"
func formatSpotifyUri(id string) (string, error) {
	parts := strings.Split(id, ":")
	if len(parts) == 3 && parts[0] == "spotify" {
		return fmt.Sprintf("https://opem.spotify.com/%s/%s", parts[1], parts[2]), nil
	} else {
		return "", fmt.Errorf("Invalid Spotify ID \"%v\"", id)
	}
}