package main

import (
	"fmt"
	"gorm.io/driver/sqlite"
	"encoding/json"
	"gorm.io/gorm"
	"log/slog"
	"time"
)

type ArtistProfile struct {
	gorm.Model
	SpotifyID  string `gorm:"unique"`
	Name       string
	Popularity int
	Genres     []Genre `gorm:"many2many:artist_genres;"`
}

type Genre struct {
	gorm.Model
	Name string `gorm:"unique"`
}

func setupTestDatabase(name string) *gorm.DB {
	slog.Info("[GOMUSIC] Setting up new test database in memory")
	// Open a named DB instance in memory so each test has a clean environment
	dbName := fmt.Sprintf("file:%s?mode=memory&cache=shared", name)
	db, err := gorm.Open(sqlite.Open(dbName), &gorm.Config{})
	if err != nil {
		panic("Failed to open database")
	}

	db.AutoMigrate(&ArtistProfile{}, &Genre{})
	return db
}

func setupDatabase() *gorm.DB {
	slog.Info("[GOMUSIC] Setting up database and running auto migrations")
	db, err := gorm.Open(sqlite.Open("gomusic.db"), &gorm.Config{})
	if err != nil {
		panic("Failed to open database")
	}

	db.AutoMigrate(&ArtistProfile{}, &Genre{})
	return db
}

// Some functions to control JSON marshalling of DB structs
func (p *ArtistProfile) MarshalJSON() ([]byte, error) {
    type CleanedProfile struct {
		UpdatedAt time.Time
		SpotifyID string
		Name string
		Popularity int
        Genres []string
    }

	artistGenres := make([]string, 0, len(p.Genres))
	for _, val := range p.Genres {
		artistGenres = append(artistGenres, val.Name)
	}

    t := CleanedProfile{
		UpdatedAt: p.UpdatedAt,
        SpotifyID: p.SpotifyID,
        Name: p.Name,
		Popularity: p.Popularity,
		Genres: artistGenres,
    }
    return json.Marshal(&t)
}

func (g *Genre) MarshalJSON() ([]byte, error) {
	type CleanedGenre struct {
		Name string
		CreatedAt time.Time
	}

	t := CleanedGenre{
		Name: g.Name,
		CreatedAt: g.CreatedAt,
	}

	return json.Marshal(&t)
}