// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package main

import (
	"bytes"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"

	"git.secluded.site/np/cmd"
	"github.com/spf13/cobra"
	"github.com/spf13/cobra/doc"
)

func main() {
	out := flag.String("out", "./docs/cli", "output directory")
	format := flag.String("format", "markdown", "markdown|man|rest")
	front := flag.Bool("frontmatter", false, "prepend simple YAML front matter to markdown")
	single := flag.String("single", "", "generate single consolidated file with this name (markdown only)")
	flag.Parse()

	if err := os.MkdirAll(*out, 0o755); err != nil {
		log.Fatal(err)
	}

	root := cmd.RootCmd()
	root.DisableAutoGenTag = true

	switch *format {
	case "markdown":
		if *single != "" {
			if err := genSingleMarkdown(root, filepath.Join(*out, *single), *front); err != nil {
				log.Fatal(err)
			}
		} else if *front {
			prep := func(filename string) string {
				base := filepath.Base(filename)
				name := strings.TrimSuffix(base, filepath.Ext(base))
				title := strings.ReplaceAll(name, "_", " ")
				return fmt.Sprintf("---\ntitle: %q\nslug: %q\ndescription: \"CLI reference for %s\"\n---\n\n", title, name, title)
			}
			link := func(name string) string { return strings.ToLower(name) }
			if err := doc.GenMarkdownTreeCustom(root, *out, prep, link); err != nil {
				log.Fatal(err)
			}
		} else {
			if err := doc.GenMarkdownTree(root, *out); err != nil {
				log.Fatal(err)
			}
		}
	case "man":
		hdr := &doc.GenManHeader{Title: strings.ToUpper(root.Name()), Section: "1"}
		if err := doc.GenManTree(root, hdr, *out); err != nil {
			log.Fatal(err)
		}
	case "rest":
		if err := doc.GenReSTTree(root, *out); err != nil {
			log.Fatal(err)
		}
	default:
		log.Fatalf("unknown format: %s", *format)
	}
}

func genSingleMarkdown(root *cobra.Command, outFile string, frontMatter bool) error {
	var buf bytes.Buffer

	if frontMatter {
		buf.WriteString("---\n")
		buf.WriteString("title: \"LLM CLI Reference\"\n")
		buf.WriteString("description: \"Complete CLI reference for LLM-oriented commands\"\n")
		buf.WriteString("---\n\n")
	}

	buf.WriteString("# LLM CLI Reference\n\n")
	buf.WriteString(root.Long)
	buf.WriteString("\n\n")

	for _, subCmd := range root.Commands() {
		if subCmd.IsAvailableCommand() && !subCmd.Hidden {
			if err := walkCommands(subCmd, &buf, 2); err != nil {
				return err
			}
		}
	}

	return os.WriteFile(outFile, buf.Bytes(), 0o644)
}

func walkCommands(cmd *cobra.Command, buf *bytes.Buffer, level int) error {
	heading := strings.Repeat("#", level)
	fmt.Fprintf(buf, "%s `%s`\n\n", heading, cmd.CommandPath())

	if cmd.Long != "" {
		buf.WriteString(cmd.Long)
		buf.WriteString("\n\n")
	} else if cmd.Short != "" {
		buf.WriteString(cmd.Short)
		buf.WriteString("\n\n")
	}

	if cmd.Runnable() {
		buf.WriteString("**Usage:**\n\n```\n")
		buf.WriteString(cmd.UseLine())
		buf.WriteString("\n```\n\n")
	}

	flags := cmd.NonInheritedFlags()
	if flags.HasAvailableFlags() {
		buf.WriteString("**Options:**\n\n```\n")
		buf.WriteString(flags.FlagUsages())
		buf.WriteString("```\n\n")
	}

	if cmd.Example != "" {
		buf.WriteString("**Examples:**\n\n```\n")
		buf.WriteString(cmd.Example)
		buf.WriteString("\n```\n\n")
	}

	for _, subCmd := range cmd.Commands() {
		if subCmd.IsAvailableCommand() && !subCmd.Hidden {
			if err := walkCommands(subCmd, buf, level+1); err != nil {
				return err
			}
		}
	}

	return nil
}
