package cmd

import (
	"context"
	"fmt"

	"github.com/hardhacker/podwise-cli/internal/api"
	"github.com/hardhacker/podwise-cli/internal/config"
	"github.com/hardhacker/podwise-cli/internal/episode"
	"github.com/spf13/cobra"
)

// podwise clip <subcommand>
var clipCmd = &cobra.Command{
	Use:   "clip <subcommand>",
	Short: "List or export your episode clips",
	Long:  "Manage clips you saved in Podwise for podcast episodes: list clips by episode, or export them when available.",
	Example: `  podwise clip list https://podwise.ai/dashboard/episodes/7360326 --json
  podwise clip export markdown https://podwise.ai/dashboard/episodes/7360326
  podwise clip export obsidian https://podwise.ai/dashboard/episodes/7360326
  podwise clip export readwise https://podwise.ai/dashboard/episodes/7360326
  podwise clip export notion https://podwise.ai/dashboard/episodes/7360326`,
}

var clipListJSONOutput bool

// podwise clip list <episode-url>
var clipListCmd = &cobra.Command{
	Use:   "list <episode-url>",
	Short: "List your clips for an episode",
	Long:  `List all clips the authenticated user saved for a Podwise episode.`,
	Example: `  podwise clip list https://podwise.ai/dashboard/episodes/7360326
  podwise clip list https://podwise.ai/dashboard/episodes/7360326 --json`,
	Args: cobra.ExactArgs(1),
	RunE: runClipList,
}

var clipExportMarkdownOutput string
var clipExportObsidianFolder string

// podwise clip export
var clipExportCmd = &cobra.Command{
	Use:   "export <subcommand>",
	Short: "Export episode clips to files or services (Readwise, Notion)",
	Long:  "Export clips for a Podwise episode — for example to a Markdown file generated by the Podwise API.",
	Example: `  podwise clip export markdown https://podwise.ai/dashboard/episodes/7360326
  podwise clip export obsidian https://podwise.ai/dashboard/episodes/7360326
  podwise clip export readwise https://podwise.ai/dashboard/episodes/7360326
  podwise clip export notion https://podwise.ai/dashboard/episodes/7360326`,
}

// podwise clip export markdown <episode-url>
var clipExportMarkdownCmd = &cobra.Command{
	Use:   "markdown <episode-url>",
	Short: "Export ready clips to a local Markdown file",
	Long:  "Download a Markdown document that includes every ready clip for this episode.",
	Example: `  podwise clip export markdown https://podwise.ai/dashboard/episodes/7360326
  podwise clip export markdown https://podwise.ai/dashboard/episodes/7360326 --output ~/notes/podcasts`,
	Args: cobra.ExactArgs(1),
	RunE: runClipExportMarkdown,
}

// podwise clip export obsidian <episode-url>
var clipExportObsidianCmd = &cobra.Command{
	Use:   "obsidian <episode-url>",
	Short: "Save clips Markdown into your Obsidian vault",
	Long: `Download a Markdown file of ready clips, then save it into your Obsidian vault.

The vault is located automatically from Obsidian's configuration file (obsidian.json).

If no vault can be found the .md file is written to the current directory with instructions for manual import.`,
	Example: `  podwise clip export obsidian https://podwise.ai/dashboard/episodes/7360326
  podwise clip export obsidian https://podwise.ai/dashboard/episodes/7360326 --folder Podcasts/2026`,
	Args: cobra.ExactArgs(1),
	RunE: runClipExportObsidian,
}

// podwise clip export readwise <episode-url>
var clipExportReadwiseCmd = &cobra.Command{
	Use:     "readwise <episode-url>",
	Short:   "Send ready clips to Readwise Highlights",
	Long:    "Send every ready clip for this episode to Readwise Highlights",
	Example: `  podwise clip export readwise https://podwise.ai/dashboard/episodes/7360326`,
	Args:    cobra.ExactArgs(1),
	RunE:    runClipExportReadwise,
}

// podwise clip export notion <episode-url>
var clipExportNotionCmd = &cobra.Command{
	Use:     "notion <episode-url>",
	Short:   "Send ready clips to Notion",
	Long:    "Send every ready clip for this episode to your configured Notion clip database.",
	Example: `  podwise clip export notion https://podwise.ai/dashboard/episodes/7360326`,
	Args:    cobra.ExactArgs(1),
	RunE:    runClipExportNotion,
}

func init() {
	clipListCmd.Flags().BoolVar(&clipListJSONOutput, "json", false, "output results as formatted JSON instead of markdown")
	clipExportMarkdownCmd.Flags().StringVar(&clipExportMarkdownOutput, "output", "", "directory to write the .md file into (default: current directory)")
	clipExportObsidianCmd.Flags().StringVar(&clipExportObsidianFolder, "folder", "", "vault-relative folder to place the note in (e.g. Podcasts/2026); defaults to vault root")

	clipExportCmd.AddCommand(clipExportMarkdownCmd)
	clipExportCmd.AddCommand(clipExportObsidianCmd)
	clipExportCmd.AddCommand(clipExportReadwiseCmd)
	clipExportCmd.AddCommand(clipExportNotionCmd)
	clipCmd.AddCommand(clipListCmd)
	clipCmd.AddCommand(clipExportCmd)
}

func runClipList(cmd *cobra.Command, args []string) error {
	seq, err := episode.ParseSeq(args[0])
	if err != nil {
		return err
	}

	cfg, err := config.Load()
	if err != nil {
		return err
	}
	if err := config.Validate(cfg); err != nil {
		return err
	}

	client := api.New(cfg.APIBaseURL, cfg.APIKey)
	result, err := episode.FetchEpisodeClips(context.Background(), client, seq)
	if err != nil {
		return err
	}

	if clipListJSONOutput {
		data, err := result.FormatJSON()
		if err != nil {
			return err
		}
		fmt.Fprintln(cmd.OutOrStdout(), string(data))
		return nil
	}

	printMarkdown(cmd, result.FormatText())
	return nil
}

func runClipExportMarkdown(cmd *cobra.Command, args []string) error {
	seq, err := episode.ParseSeq(args[0])
	if err != nil {
		return fmt.Errorf("invalid episode: %w", err)
	}

	cfg, err := config.Load()
	if err != nil {
		return err
	}
	if err := config.Validate(cfg); err != nil {
		return err
	}

	opts := episode.ClipsMarkdownExportOptions{
		OutputDir: clipExportMarkdownOutput,
	}

	client := api.New(cfg.APIBaseURL, cfg.APIKey)
	ctx := context.Background()

	fmt.Printf("Exporting clips for %s...\n", episode.BuildEpisodeURL(seq))

	result, err := episode.ExportClipsToMarkdown(ctx, client, seq, opts)
	if err != nil {
		return err
	}

	fmt.Printf("\n✓ Clips Markdown file saved\n")
	fmt.Printf("  File: %s\n", result.FilePath)
	fmt.Printf("  Ready clips included: %d\n", result.SuccessCount)
	if result.UnexportableClipCount > 0 {
		fmt.Printf("  Not ready / skipped: %d\n", result.UnexportableClipCount)
	}

	return nil
}

func runClipExportObsidian(cmd *cobra.Command, args []string) error {
	seq, err := episode.ParseSeq(args[0])
	if err != nil {
		return fmt.Errorf("invalid episode: %w", err)
	}

	cfg, err := config.Load()
	if err != nil {
		return err
	}
	if err := config.Validate(cfg); err != nil {
		return err
	}

	client := api.New(cfg.APIBaseURL, cfg.APIKey)
	ctx := context.Background()

	fmt.Printf("Fetching clips Markdown for %s for Obsidian export...\n", episode.BuildEpisodeURL(seq))

	result, err := episode.ExportClipsToObsidian(ctx, client, seq, clipExportObsidianFolder)
	if err != nil {
		return err
	}

	if result.WrittenToVault {
		fmt.Printf("\n✓ Saved to Obsidian vault\n")
		fmt.Printf("  Path: %s\n", result.FilePath)
	} else {
		fmt.Printf("\n✓ Markdown file saved (Obsidian vault not found)\n")
		fmt.Printf("  File: %s\n", result.FilePath)
		fmt.Printf("\n  To import manually:\n")
		fmt.Printf("  • Drag and drop %s into the Obsidian File Explorer, or\n", result.FilePath)
		fmt.Printf("  • Copy the file directly into your Obsidian vault folder\n")
	}
	fmt.Printf("  Ready clips included: %d\n", result.SuccessCount)
	if result.UnexportableClipCount > 0 {
		fmt.Printf("  Not ready / skipped: %d\n", result.UnexportableClipCount)
	}

	return nil
}

func runClipExportReadwise(cmd *cobra.Command, args []string) error {
	seq, err := episode.ParseSeq(args[0])
	if err != nil {
		return fmt.Errorf("invalid episode: %w", err)
	}

	cfg, err := config.Load()
	if err != nil {
		return err
	}
	if err := config.Validate(cfg); err != nil {
		return err
	}

	client := api.New(cfg.APIBaseURL, cfg.APIKey)
	ctx := context.Background()

	fmt.Printf("Sending clips to Readwise for %s...\n", episode.BuildEpisodeURL(seq))

	result, err := episode.ExportClipsToReadwise(ctx, client, seq)
	if err != nil {
		return err
	}

	fmt.Printf("\n✓ Clips sent to Readwise Highlights\n")
	fmt.Printf("  URL: %s\n", result.URL)
	fmt.Printf("  Ready clips sent: %d\n", result.SuccessCount)
	if result.UnexportableClipCount > 0 {
		fmt.Printf("  Not ready / skipped: %d\n", result.UnexportableClipCount)
	}

	return nil
}

func runClipExportNotion(cmd *cobra.Command, args []string) error {
	seq, err := episode.ParseSeq(args[0])
	if err != nil {
		return fmt.Errorf("invalid episode: %w", err)
	}

	cfg, err := config.Load()
	if err != nil {
		return err
	}
	if err := config.Validate(cfg); err != nil {
		return err
	}

	client := api.New(cfg.APIBaseURL, cfg.APIKey)
	ctx := context.Background()

	fmt.Printf("Sending clips to Notion for %s...\n", episode.BuildEpisodeURL(seq))

	result, err := episode.ExportClipsToNotion(ctx, client, seq)
	if err != nil {
		return err
	}

	fmt.Printf("\n✓ Clips sent to Notion\n")
	fmt.Printf("  Page URL: %s\n", result.URL)
	fmt.Printf("  Ready clips sent: %d\n", result.SuccessCount)
	if result.UnexportableClipCount > 0 {
		fmt.Printf("  Not ready / skipped: %d\n", result.UnexportableClipCount)
	}

	return nil
}
