package main

import (
	"flag"
	"log"
	"net/http"
	"strconv"
	"strings"

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

var (
	flagMetadataPath string
	flagAutoplay     string
)

func init() {
	flag.StringVar(&flagMetadataPath, "m", "data/metadata", "Path to enriched metadata")
	flag.StringVar(&flagAutoplay, "autoplay", "048794", "Value to set for autoplay field in /api/songs")
}

func handleAPINew(metadata *monstersirenfetch.Metadata) http.HandlerFunc {
	if metadata == nil {
		log.Fatal("invalid metadata")
	}

	const (
		// TODO(ophestra): stub these out with local artwork
		fontsetResp    = `{"code":0,"msg":"","data":{"Sans-Regular":{"tt":"/static/SourceHanSansCN-Regular.ttf","eot":"/static/SourceHanSansCN-Regular.eot","svg":"/static/SourceHanSansCN-Regular.svg","woff":"/static/SourceHanSansCN-Regular.woff"},"Sans-Bold":{"tt":"/static/SourceHanSansCN-Bold.ttf","eot":"/static/SourceHanSansCN-Bold.eot","svg":"/static/SourceHanSansCN-Bold.svg","woff":"/static/SourceHanSansCN-Bold.woff"}}}`
		recommendsResp = `{"code":0,"msg":"","data":[{"title":"#AUS小屋","coverUrl":"https://web.hycdn.cn/siren/pic/20230228/ba2bf4c42b3852a8b35e9721a8c8bbb7.jpg","cover":{"private":false,"path":"siren/pic/20230228/ba2bf4c42b3852a8b35e9721a8c8bbb7.jpg"},"description":"\"嗨，各位，这个冬天过得怎么样？\n我们一直呆在室内，眼看着春天到来，再不出门，雪就要化了，于是大家都被dan拉着去比赛堆雪人。虽然能动弹动弹是很不错，但“这是为了阻止alty祸害厨房”这句话就很多余了不是吗！\n我和frost堆到一半，决定给雪人戴一个耳朵头箍，frost还把围巾也围上去了，造就了一个可爱的卡特斯。就在我们以为赢定了的时候，回头看见dan正站在一个巨大的雪人旁边手舞足蹈。呃，不得不说气势很惊人，有一瞬间甘拜下风的念头。\n但是看了看被惊到的aya旁边的……小雪人，我觉得我和frost的雪人至少","type":2,"data":"750452"},{"title":"#EMPEROR","coverUrl":"https://web.hycdn.cn/siren/pic/20230122/89969a75098c07cd8e289bad831ea4a2.jpg","cover":{"private":false,"path":"siren/pic/20230122/89969a75098c07cd8e289bad831ea4a2.jpg"},"description":"","type":2,"data":"578833"},{"title":"#AUS小屋","coverUrl":"https://web.hycdn.cn/siren/pic/20221128/ede2a04423632c17b702a656414a8c04.jpg","cover":{"private":false,"path":"siren/pic/20221128/ede2a04423632c17b702a656414a8c04.jpg"},"description":"一起用被炉（有点热！）","type":2,"data":"750452"},{"title":"#AUS小屋","coverUrl":"https://web.hycdn.cn/siren/pic/20220930/f4c7886eabcc1f3f178e7d4a9e5f7a21.jpg","cover":{"private":false,"path":"siren/pic/20220930/f4c7886eabcc1f3f178e7d4a9e5f7a21.jpg"},"description":"","type":2,"data":"336217"},{"title":"#D.D.D.PHOTO","coverUrl":"https://web.hycdn.cn/siren/pic/20221228/93393e28e1d0caff9b61c951eaf6a5f5.jpg","cover":{"private":false,"path":"siren/pic/20221228/93393e28e1d0caff9b61c951eaf6a5f5.jpg"},"description":"","type":2,"data":"241307"},{"title":"live演出","coverUrl":"https://web.hycdn.cn/siren/pic/20230427/b524e7b99982a972609de43998f61b46.jpg","cover":{"private":false,"path":"siren/pic/20230427/b524e7b99982a972609de43998f61b46.jpg"},"description":"\"春天好，各位。AUS与仲春一起归来了。\n今天我们刚结束了新live的最后一场演出。我站在舞台中央，被音浪和节奏包围着，即使晃眼的灯光遮挡了视线，也能感受到大家在台下拼命挥舞双手，这同样让我很激动。\n我唱哑了嗓子，alty弹到指头隐隐作痛，frost不时就会揉揉手腕，一向精力充沛的dan回工作室后也累瘫了，但我们一路笑得很大声，连frost也在旁边勾着嘴角。毕竟对于创作者来说，欣赏者的热爱足以融化春寒和创作的倦怠，对吧？\"","type":2,"data":"605965"}]}`
	)

	var (
		fontsetRespData    = []byte(fontsetResp)
		recommendsRespData = []byte(recommendsResp)
	)

	var albumsRespData []byte
	{
		resp := monstersirenfetch.AlbumsResponse{Data: make(monstersirenfetch.AlbumsData, len(metadata.Albums))}
		for i := range metadata.Albums {
			if !metadata.Albums[i].Copy(&resp.Data[i], monstersirenfetch.AlbumVariantBase) {
				log.Fatal("cannot copy album metadata for base variant")
			}
		}
		albumsRespData = mustMarshalJSON(resp)
	}

	// data, detail
	albumCidData := make(map[int][2][]byte, len(metadata.Albums))
	for i := range metadata.Albums {
		var (
			a = &metadata.Albums[i]
			v monstersirenfetch.AlbumResponse
			d [2][]byte
		)

		if !a.Copy(&v.Data, monstersirenfetch.AlbumVariantData) {
			log.Fatal("cannot copy album metadata for data variant")
		}
		d[0] = mustMarshalJSON(&v)

		if !a.Copy(&v.Data, monstersirenfetch.AlbumVariantDetail) {
			log.Fatal("cannot copy album metadata for detail variant")
		}
		d[1] = mustMarshalJSON(&v)

		albumCidData[int(a.CID)] = d
	}
	if len(albumCidData) != len(metadata.Albums) {
		log.Fatalf("album has duplicate cid: %d != %d", len(albumCidData), len(metadata.Albums))
	}

	var songsRespData []byte
	{
		resp := monstersirenfetch.SongsResponse{Data: monstersirenfetch.SongsData{
			List:     make([]monstersirenfetch.Song, len(metadata.Songs)),
			Autoplay: flagAutoplay,
		}}
		for i := range metadata.Songs {
			if !metadata.Songs[i].Copy(&resp.Data.List[i], monstersirenfetch.SongVariantBase) {
				log.Fatal("cannot copy song metadata for base variant")
			}
		}
		songsRespData = mustMarshalJSON(resp)
	}

	songsCidData := make(map[int][]byte, len(metadata.Songs))
	for i := range metadata.Songs {
		var (
			s = metadata.Songs[i]
			v monstersirenfetch.SongResponse
		)

		if !s.Copy(&v.Data, monstersirenfetch.SongVariantFull) {
			log.Fatal("cannot copy song metadata for full variant")
		}
		songsCidData[int(s.CID)] = mustMarshalJSON(&v)
	}
	if len(songsCidData) != len(metadata.Songs) {
		log.Fatalf("song has duplicate cid: %d != %d", len(songsCidData), len(metadata.Songs))
	}

	log.Printf("loaded %d albums and %d songs", len(metadata.Albums), len(metadata.Songs))
	return func(writer http.ResponseWriter, request *http.Request) {
		if request.URL == nil {
			log.Printf("got invalid request %p", request)
			return
		}

		const (
			prefix        = "/api/"
			endpointAlbum = prefix + "album/"
			endpointSong  = prefix + "song/"

			endpointAlbumSuffixData   = "/data"
			endpointAlbumSuffixDetail = "/detail"
		)

		switch request.URL.Path {
		case prefix + "fontset":
			writeResp(writer, fontsetRespData)

		case prefix + "recommends":
			writeResp(writer, recommendsRespData)

		case prefix + "albums":
			writeResp(writer, albumsRespData)

		case prefix + "songs":
			writeResp(writer, songsRespData)

		default:
			if strings.HasPrefix(request.URL.Path, endpointAlbum) {
				v := request.URL.Path[len(endpointAlbum):]

				detail := strings.HasSuffix(v, endpointAlbumSuffixDetail)
				if detail {
					v = v[:len(v)-len(endpointAlbumSuffixDetail)]
				} else if strings.HasSuffix(v, endpointAlbumSuffixData) {
					v = v[:len(v)-len(endpointAlbumSuffixData)]
				} else {
					writer.WriteHeader(http.StatusNotFound)
					writeResp(writer, []byte("unsupported album endpoint"))
					return
				}

				if c, err := strconv.Atoi(v); err != nil {
					writer.WriteHeader(http.StatusBadRequest)
					writeResp(writer, []byte("invalid cid"))
					return
				} else if albumData, ok := albumCidData[c]; !ok {
					writer.WriteHeader(http.StatusNotFound)
					writeResp(writer, []byte("not found"))
					return
				} else if detail {
					writeResp(writer, albumData[1])
					return
				} else {
					writeResp(writer, albumData[0])
					return
				}
			}

			if strings.HasPrefix(request.URL.Path, endpointSong) {
				v := request.URL.Path[len(endpointSong):]
				if c, err := strconv.Atoi(v); err != nil {
					writer.WriteHeader(http.StatusBadRequest)
					writeResp(writer, []byte("invalid cid"))
					return
				} else if songData, ok := songsCidData[c]; !ok {
					writer.WriteHeader(http.StatusNotFound)
					writeResp(writer, []byte("not found"))
					return
				} else {
					writeResp(writer, songData)
					return
				}
			}

			verboseln("api endpoint", request.URL.Path, "not implemented")
			writer.WriteHeader(http.StatusNotFound)
			writeResp(writer, []byte("null"))
		}
	}
}
