package cmd

import (
	"encoding/json"
	"fmt"
	"os"
	"strings"
	"text/tabwriter"

	"github.com/spf13/cobra"
)

var reportsCmd = &cobra.Command{
	Use:   "reports",
	Short: "View generated reports and artifacts",
}

var reportsListCmd = &cobra.Command{
	Use:     "list",
	Short:   "List all artifacts in Studio",
	Aliases: []string{"ls"},
	Run: func(cmd *cobra.Command, args []string) {
		client, cfg := mustClient()
		wsID := mustWorkspace(cfg)
		artifacts, err := client.GetArtifacts(wsID)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}
		if len(artifacts) == 0 {
			fmt.Println("No artifacts/reports in workspace.")
			return
		}
		w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
		fmt.Fprintln(w, "ID\tTYPE\tTITLE\tSOURCE")
		for _, a := range artifacts {
			fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", a.ID, a.Type, a.Title, a.SourceID)
		}
		w.Flush()
	},
}

var reportsGetCmd = &cobra.Command{
	Use:   "get <report-id|latest>",
	Short: "Get a specific report/artifact",
	Args:  cobra.ExactArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		client, cfg := mustClient()
		wsID := mustWorkspace(cfg)
		format, _ := cmd.Flags().GetString("format")

		artifacts, err := client.GetArtifacts(wsID)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}
		if len(artifacts) == 0 {
			fmt.Fprintln(os.Stderr, "No artifacts found.")
			os.Exit(1)
		}

		target := args[0]
		var foundIdx int = -1
		if target == "latest" {
			foundIdx = len(artifacts) - 1
		} else {
			for i, a := range artifacts {
				if a.ID == target {
					foundIdx = i
					break
				}
			}
		}
		if foundIdx < 0 {
			fmt.Fprintf(os.Stderr, "Artifact %q not found\n", target)
			os.Exit(1)
		}
		a := artifacts[foundIdx]

		if format == "json" {
			enc := json.NewEncoder(os.Stdout)
			enc.SetIndent("", "  ")
			_ = enc.Encode(a)
			return
		}

		fmt.Printf("=== %s ===\n", a.Title)
		fmt.Printf("ID:   %s\n", a.ID)
		fmt.Printf("Type: %s\n", a.Type)
		fmt.Println()
		if a.Data != nil {
			renderReportData(a.Data)
		}
	},
}

func renderReportData(data json.RawMessage) {
	var parsed map[string]interface{}
	if err := json.Unmarshal(data, &parsed); err != nil {
		fmt.Println(string(data))
		return
	}
	if v, ok := parsed["summary"]; ok {
		fmt.Println("## Summary")
		fmt.Println(formatField(v))
		fmt.Println()
	}
	if v, ok := parsed["root_cause"]; ok {
		fmt.Println("## Root Cause")
		fmt.Println(formatField(v))
		fmt.Println()
	}
	if v, ok := parsed["recommendations"]; ok {
		fmt.Println("## Recommendations")
		if recs, ok := v.([]interface{}); ok {
			for i, r := range recs {
				fmt.Printf("  %d. %s\n", i+1, formatField(r))
			}
		} else {
			fmt.Println(formatField(v))
		}
		fmt.Println()
	}
	if v, ok := parsed["metrics"]; ok {
		fmt.Println("## Metrics")
		if ms, ok := v.([]interface{}); ok {
			for _, m := range ms {
				if mm, ok := m.(map[string]interface{}); ok {
					name := getString(mm, "name")
					desc := getString(mm, "description")
					fmt.Printf("  - %s", name)
					if desc != "" {
						fmt.Printf(": %s", desc)
					}
					fmt.Println()
				}
			}
		}
		fmt.Println()
	}
	if v, ok := parsed["events"]; ok {
		fmt.Println("## Events")
		if es, ok := v.([]interface{}); ok {
			for _, e := range es {
				if ee, ok := e.(map[string]interface{}); ok {
					ts := getString(ee, "timestamp")
					title := getString(ee, "title")
					desc := getString(ee, "description")
					if ts != "" {
						fmt.Printf("  [%s] ", ts)
					} else {
						fmt.Print("  ")
					}
					fmt.Print(title)
					if desc != "" {
						fmt.Printf(" - %s", desc)
					}
					fmt.Println()
				}
			}
		}
		fmt.Println()
	}
}

func getString(m map[string]interface{}, key string) string {
	if v, ok := m[key]; ok {
		return fmt.Sprintf("%v", v)
	}
	return ""
}

func formatField(v interface{}) string {
	switch t := v.(type) {
	case string:
		return t
	default:
		b, _ := json.MarshalIndent(t, "  ", "  ")
		return strings.TrimSpace(string(b))
	}
}

func init() {
	reportsGetCmd.Flags().String("format", "text", "output format: text or json")
	reportsCmd.AddCommand(reportsListCmd)
	reportsCmd.AddCommand(reportsGetCmd)
	rootCmd.AddCommand(reportsCmd)
}
