package main

import (
	"context"
	"flag"
	"log"
	"slices"

	"git.gensokyo.uk/yonah/monstersirenfetch"
)

var (
	flagAlbumsPath string
	flagSongsPath  string
	flagOutputPath string
)

func init() {
	flag.StringVar(&flagAlbumsPath, "a", "albums.json",
		"Path to file containing the response body of /api/albums")
	flag.StringVar(&flagSongsPath, "s", "songs.json",
		"Path to file containing the response body of /api/songs")
	flag.StringVar(&flagOutputPath, "o", "metadata.json",
		"Path to write enriched metadata")
}

func mustEnrich(ctx context.Context) {
	var (
		albumsResponse monstersirenfetch.AlbumsResponse
		songsResponse  monstersirenfetch.SongsResponse
	)
	mustReadJSON(flagAlbumsPath, &albumsResponse)
	mustReadJSON(flagSongsPath, &songsResponse)

	n := new(netDirect)
	for i := range albumsResponse.Data {
		a := &albumsResponse.Data[i]
		if !a.IsFull() {
			if err := a.Enrich(ctx, n); err != nil {
				log.Fatal(err)
			}
			log.Printf("enriched album %s (%s) with %d songs", a.CID.String(), a.Name, len(a.Songs))
		} else {
			log.Printf("skipped album %s (%s)", a.CID.String(), a.Name)
		}
	}
	for i := range songsResponse.Data.List {
		s := &songsResponse.Data.List[i]
		if !s.IsFull() {
			if err := s.Enrich(ctx, n); err != nil {
				log.Fatal(err)
			}
			log.Printf("enriched song %s: %s (%s)", s.CID.String(), s.SourceURL, s.Name)
		} else {
			log.Printf("skipped song %s: %s (%s)", s.CID.String(), s.SourceURL, s.Name)
		}
	}

	// consistency check: enriched songs match flattened songs
	if c, err := monstersirenfetch.Flatten(albumsResponse.Data, songsResponse.Data); err != nil {
		log.Fatal(err)
	} else {
		for _, ca := range c {
			if ca.Album == nil {
				log.Fatal("albums contain nil")
			}

			flattenSongs := make([]monstersirenfetch.AlbumSong, 0, len(ca.Songs))
			for _, cs := range ca.Songs {
				if cs == nil {
					log.Fatal("songs contain nil")
				}
				flattenSongs = append(flattenSongs, monstersirenfetch.AlbumSong{CID: cs.CID, Name: cs.Name, Artists: cs.Artists})

			}
			slices.SortFunc(flattenSongs, func(a, b monstersirenfetch.AlbumSong) int { return int(a.CID - b.CID) })

			enrichSongs := make([]monstersirenfetch.AlbumSong, len(ca.Album.Songs))
			copy(enrichSongs, ca.Album.Songs)
			slices.SortFunc(enrichSongs, func(a, b monstersirenfetch.AlbumSong) int { return int(a.CID - b.CID) })

			if !slices.EqualFunc(flattenSongs, enrichSongs, func(a monstersirenfetch.AlbumSong, b monstersirenfetch.AlbumSong) bool {
				return a.CID == b.CID && a.Name == b.Name && slices.Equal(a.Artists, b.Artists)
			}) {
				log.Fatalf("album %s enrichment inconsistent with flatten state", ca.Album.Name)
			} else {
				log.Printf("validated %d songs associated with album %s", len(enrichSongs), ca.Album.CID.String())
			}
		}
	}

	mustWriteJSON(flagOutputPath, &monstersirenfetch.Metadata{
		Albums: albumsResponse.Data,
		Songs:  songsResponse.Data.List,
	})
	log.Println("metadata written to", flagOutputPath)
}
