package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"os"

	"github.com/gmgauthier/gostations/internal/config"
	playerpkg "github.com/gmgauthier/gostations/internal/player"
	"github.com/gmgauthier/gostations/internal/radio"
	"github.com/gmgauthier/gostations/internal/ui"
)

var version string

func showVersion() {
	fmt.Println(version)
}

func precheck() {
	p := "mpv"
	if v, err := config.Get("player.command"); err == nil && v != "" {
		p = v
	}
	if !playerpkg.IsInstalled(p) {
		fmt.Printf("%s is either not installed, or not on your $PATH. Cannot continue.\n", p)
		os.Exit(1)
	}
}

// runFind implements the "find" subcommand for scripting / non-interactive lookup.
// Usage: gostations find [-c country] [-t tags] ... [-x] [-j]
func runFind(args []string) {
	fs := flag.NewFlagSet("find", flag.ExitOnError)
	var (
		name    string
		country string
		state   string
		tags    string
		notok   bool
		jsonOut bool
	)
	fs.StringVar(&name, "n", "", "Station name (or identifier).")
	fs.StringVar(&country, "c", "", "Home country.")
	fs.StringVar(&state, "s", "", "Home state (if in the United States).")
	fs.StringVar(&tags, "t", "", "Tag (or comma-separated tag list)")
	fs.BoolVar(&notok, "x", false, "If toggled, will show stations that are down")
	fs.BoolVar(&jsonOut, "j", false, "Output as JSON array (for scripting)")
	fs.BoolVar(&jsonOut, "json", false, "Output as JSON array (for scripting)")

	fs.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: gostations find [options]\n\nOptions:\n")
		fs.PrintDefaults()
	}
	_ = fs.Parse(args)

	if err := config.Init(); err != nil {
		fmt.Fprintf(os.Stderr, "config: %v\n", err)
		os.Exit(1)
	}

	stations, err := radio.Search(context.Background(), name, country, state, tags, notok)
	if err != nil {
		fmt.Fprintf(os.Stderr, "search: %v\n", err)
		os.Exit(1)
	}

	if jsonOut {
		b, _ := json.MarshalIndent(stations, "", "  ")
		fmt.Println(string(b))
		return
	}

	// human/script friendly list (similar to old output)
	fmt.Println("...Found Stations...")
	for i, s := range stations {
		listing := fmt.Sprintf("%-40s   %-5s %-5s %s", Short(s.Name, 40), s.Codec, s.Bitrate, s.Url)
		fmt.Printf("%d) %s\n", i+1, listing)
	}
	if len(stations) == 0 {
		fmt.Println("(no stations matched)")
	}
}

// runPlay implements the "play" subcommand for scripting direct playback.
// It accepts the same search flags or a direct URL as first positional arg.
// Plays the first match (or the URL) using the configured player and blocks.
func runPlay(args []string) {
	fs := flag.NewFlagSet("play", flag.ExitOnError)
	var (
		name    string
		country string
		state   string
		tags    string
		notok   bool
	)
	fs.StringVar(&name, "n", "", "Station name (or identifier).")
	fs.StringVar(&country, "c", "", "Home country.")
	fs.StringVar(&state, "s", "", "Home state (if in the United States).")
	fs.StringVar(&tags, "t", "", "Tag (or comma-separated tag list)")
	fs.BoolVar(&notok, "x", false, "If toggled, will show stations that are down")

	fs.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: gostations play [options] [direct-url]\n\nOptions:\n")
		fs.PrintDefaults()
	}
	_ = fs.Parse(args)

	pos := fs.Args()

	if err := config.Init(); err != nil {
		fmt.Fprintf(os.Stderr, "config: %v\n", err)
		os.Exit(1)
	}
	precheck()

	var playURL string
	if len(pos) > 0 {
		playURL = pos[0]
	} else {
		stations, err := radio.Search(context.Background(), name, country, state, tags, notok)
		if err != nil {
			fmt.Fprintf(os.Stderr, "search: %v\n", err)
			os.Exit(1)
		}
		if len(stations) == 0 {
			fmt.Fprintln(os.Stderr, "no stations found to play")
			os.Exit(1)
		}
		playURL = stations[0].Url
		fmt.Printf("Playing first match: %s\n", stations[0].Name)
	}

	// Use legacy for now (cleaned); will use richer player in TUI/IPC later.
	pname := "mpv"
	if v, err := config.Get("player.command"); err == nil && v != "" {
		pname = v
	}
	opts := ""
	if v, err := config.Get("player.options"); err == nil {
		opts = v
	}

	leg := playerpkg.NewLegacy(pname, opts)
	if err := leg.Play(playURL); err != nil {
		fmt.Fprintf(os.Stderr, "play error: %v\n", err)
		os.Exit(1)
	}
}

func main() {
	// Early version / help for top level
	if len(os.Args) > 1 {
		switch os.Args[1] {
		case "find":
			runFind(os.Args[2:])
			return
		case "play":
			runPlay(os.Args[2:])
			return
		case "-v", "--version", "version":
			showVersion()
			return
		case "-h", "--help", "help":
			printTopHelp()
			return
		}
	}

	// Common flags (used for TUI seeding or legacy)
	var (
		name    string
		country string
		state   string
		tags    string
		notok   bool
		legacy  bool
		version bool
	)

	fs := flag.NewFlagSet("gostations", flag.ExitOnError)
	fs.StringVar(&name, "n", "", "Station name (or identifier).")
	fs.StringVar(&country, "c", "", "Home country.")
	fs.StringVar(&state, "s", "", "Home state (if in the United States).")
	fs.StringVar(&tags, "t", "", "Tag (or comma-separated tag list)")
	fs.BoolVar(&notok, "x", false, "If toggled, will show stations that are down")
	fs.BoolVar(&legacy, "legacy", false, "Force old wmenu UI (kept until new TUI is perfect)")
	fs.BoolVar(&version, "v", false, "Show version.")

	fs.Usage = printTopHelp

	_ = fs.Parse(os.Args[1:])

	if version {
		showVersion()
		return
	}

	precheck()

	if err := config.Init(); err != nil {
		fmt.Printf("config init: %v\n", err)
		os.Exit(1)
	}

	stations, err := radio.Search(context.Background(), name, country, state, tags, notok)
	if err != nil {
		fmt.Printf("warning: station search: %v\n", err)
		stations = nil
	}

	if legacy {
		// Old wmenu path (gated)
		menu := RadioMenu(stations)
		if err := menu.Run(); err != nil {
			fmt.Println(err.Error())
			os.Exit(1)
		}
		return
	}

	// Default: new TUI (Bubble Tea)
	if err := ui.Run(stations); err != nil {
		fmt.Printf("TUI error: %v\n", err)
		os.Exit(1)
	}
}

func printTopHelp() {
	fmt.Printf(`Usage:
  gostations [options]                 # Launch interactive TUI (default)
  gostations find [options]            # Non-interactive station search (scripting)
  gostations play [options] [url]      # Direct playback (scripting)
  gostations -h | --help
  gostations -v | --version

Global options:
  -n string   Station name (or identifier).
  -c string   Home country.
  -s string   Home state (if in the United States).
  -t string   Tag (or comma-separated tag list)
  -x          If toggled, will show stations that are down
  -v          Show version.
  --legacy    Force old wmenu UI (temporary)

Subcommand examples:
  gostations find -c "United Kingdom" -t "news" -j
  gostations play -c "Gambia"
  gostations play http://stream.example.com/radio.mp3

Old top-level behavior without subcommand now defaults to the new TUI.
Use --legacy to force the classic wmenu flow.
`)
}
