package cmd

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

	"github.com/navidrome/navidrome/core"
	"github.com/navidrome/navidrome/log"
	"github.com/navidrome/navidrome/model"
	"github.com/pelletier/go-toml/v2"
	"github.com/spf13/cobra"
	"gopkg.in/yaml.v3"
)

var (
	format string
)

func init() {
	inspectCmd.Flags().StringVarP(&format, "format", "f", "jsonindent", "output format (pretty, toml, yaml, json, jsonindent)")
	rootCmd.AddCommand(inspectCmd)
}

var inspectCmd = &cobra.Command{
	Use:   "inspect [files to inspect]",
	Short: "Inspect tags",
	Long:  "Show file tags as seen by Navidrome",
	Args:  cobra.MinimumNArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		runInspector(args)
	},
}

var marshalers = map[string]func(any) ([]byte, error){
	"pretty": prettyMarshal,
	"toml":   toml.Marshal,
	"yaml":   yaml.Marshal,
	"json":   json.Marshal,
	"jsonindent": func(v any) ([]byte, error) {
		return json.MarshalIndent(v, "", "  ")
	},
}

func prettyMarshal(v any) ([]byte, error) {
	out := v.([]core.InspectOutput)
	var res strings.Builder
	for i := range out {
		res.WriteString(fmt.Sprintf("====================\nFile: %s\n\n", out[i].File))
		t, _ := toml.Marshal(out[i].RawTags)
		res.WriteString(fmt.Sprintf("Raw tags:\n%s\n\n", t))
		t, _ = toml.Marshal(out[i].MappedTags)
		res.WriteString(fmt.Sprintf("Mapped tags:\n%s\n\n", t))
	}
	return []byte(res.String()), nil
}

func runInspector(args []string) {
	marshal := marshalers[format]
	if marshal == nil {
		log.Fatal("Invalid format", "format", format)
	}
	var out []core.InspectOutput
	for _, filePath := range args {
		if !model.IsAudioFile(filePath) {
			log.Warn("Not an audio file", "file", filePath)
			continue
		}
		output, err := core.Inspect(filePath, 1, "")
		if err != nil {
			log.Warn("Unable to process file", "file", filePath, "error", err)
			continue
		}

		out = append(out, *output)
	}
	data, _ := marshal(out)
	fmt.Println(string(data))
}
