package cmd

import (
	"fmt"
	"os"
	"text/tabwriter"
	"time"

	"github.com/spf13/cobra"
	"github.com/tidbcloud/investibook/cli/internal/config"
)

var workspaceCmd = &cobra.Command{
	Use:     "workspace",
	Short:   "Manage workspaces",
	Aliases: []string{"ws"},
}

var workspaceCreateCmd = &cobra.Command{
	Use:   "create",
	Short: "Create a new workspace",
	Run: func(cmd *cobra.Command, args []string) {
		client, _ := mustClient()
		name, _ := cmd.Flags().GetString("name")
		desc, _ := cmd.Flags().GetString("description")
		if name == "" {
			name = "Untitled Workspace"
		}
		ws, err := client.CreateWorkspace(name, desc)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Created workspace: %s (%s)\n", ws.Name, ws.ID)
	},
}

var workspaceListCmd = &cobra.Command{
	Use:     "list",
	Short:   "List all workspaces",
	Aliases: []string{"ls"},
	Run: func(cmd *cobra.Command, args []string) {
		client, cfg := mustClient()
		workspaces, err := client.ListWorkspaces()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}
		if len(workspaces) == 0 {
			fmt.Println("No workspaces found. Create one with: investibook workspace create")
			return
		}
		w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
		fmt.Fprintln(w, "ID\tNAME\tCREATED\tSHARED\tACTIVE")
		for _, ws := range workspaces {
			active := ""
			if ws.ID == cfg.DefaultWorkspace {
				active = "*"
			}
			shared := ""
			if ws.Shared() {
				shared = "yes"
			}
			created := ws.CreatedAt
			if len(created) > 10 {
				created = created[:10]
			}
			fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", ws.ID, ws.Name, created, shared, active)
		}
		w.Flush()
	},
}

var workspaceUseCmd = &cobra.Command{
	Use:   "use <workspace-id>",
	Short: "Set the default workspace",
	Args:  cobra.ExactArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		client, _ := mustClient()
		cfg := mustLoadConfig()
		wsID := args[0]
		ws, err := client.GetWorkspace(wsID)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}
		p := cfg.ActiveProfileData()
		p.DefaultWorkspace = ws.ID
		cfg.UpsertProfile(cfg.ActiveProfileName(), p)
		if err := config.Save(cfg); err != nil {
			fmt.Fprintf(os.Stderr, "Error saving config: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Active workspace: %s (%s)\n", ws.Name, ws.ID)
	},
}

var workspaceShowCmd = &cobra.Command{
	Use:   "show [workspace-id]",
	Short: "Show workspace details",
	Args:  cobra.MaximumNArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		client, cfg := mustClient()
		var wsID string
		if len(args) > 0 {
			wsID = args[0]
		} else {
			wsID = mustWorkspace(cfg)
		}
		ws, err := client.GetWorkspace(wsID)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("ID:          %s\n", ws.ID)
		fmt.Printf("Name:        %s\n", ws.Name)
		fmt.Printf("Description: %s\n", ws.Description)
		fmt.Printf("Owner:       %s\n", ws.UserID)
		fmt.Printf("Shared:      %v\n", ws.Shared())
		fmt.Printf("Created:     %s\n", ws.CreatedAt)
		fmt.Printf("Updated:     %s\n", ws.UpdatedAt)
	},
}

var workspaceDeleteCmd = &cobra.Command{
	Use:   "delete <workspace-id>",
	Short: "Delete a workspace",
	Args:  cobra.ExactArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		client, _ := mustClient()
		if err := client.DeleteWorkspace(args[0]); err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Deleted workspace %s\n", args[0])
	},
}

func init() {
	workspaceCreateCmd.Flags().String("name", "", "workspace name")
	workspaceCreateCmd.Flags().String("description", "", "workspace description")
	workspaceCmd.AddCommand(workspaceCreateCmd)
	workspaceCmd.AddCommand(workspaceListCmd)
	workspaceCmd.AddCommand(workspaceUseCmd)
	workspaceCmd.AddCommand(workspaceShowCmd)
	workspaceCmd.AddCommand(workspaceDeleteCmd)
	workspaceCmd.AddCommand(workspaceExportCmd)
	workspaceCmd.AddCommand(workspaceExportsCmd)
	workspaceExportCmd.Flags().Bool("no-wait", false, "start export and return immediately without waiting for completion")
	rootCmd.AddCommand(workspaceCmd)
}

// ---------------------------------------------------------------------------
// workspace export — start an export and wait for the presigned URL
// ---------------------------------------------------------------------------

var workspaceExportCmd = &cobra.Command{
	Use:   "export [workspace-id]",
	Short: "Export a workspace to S3 and print a 1-hour download URL",
	Args:  cobra.MaximumNArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		client, cfg := mustClient()
		var wsID string
		if len(args) > 0 {
			wsID = args[0]
		} else {
			wsID = mustWorkspace(cfg)
		}
		noWait, _ := cmd.Flags().GetBool("no-wait")

		task, err := client.StartExport(wsID)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Export started (task %s)\n", task.TaskID)

		if noWait {
			fmt.Printf("Poll status: investibook workspace exports --workspace %s\n", wsID)
			return
		}

		// Poll until terminal state
		fmt.Print("Compressing and uploading")
		for {
			time.Sleep(2 * time.Second)
			fmt.Print(".")
			t, err := client.GetExportStatus(wsID, task.TaskID)
			if err != nil {
				fmt.Fprintf(os.Stderr, "\nError polling status: %v\n", err)
				os.Exit(1)
			}
			if t.Status == "completed" {
				fmt.Printf("\n✓ Export ready. Download URL (valid 1 hour):\n%s\n", t.DownloadURL)
				return
			}
			if t.Status == "error" {
				fmt.Fprintf(os.Stderr, "\n✗ Export failed: %s\n", t.Error)
				os.Exit(1)
			}
		}
	},
}

// ---------------------------------------------------------------------------
// workspace exports — list all exports for the current user
// ---------------------------------------------------------------------------

var workspaceExportsCmd = &cobra.Command{
	Use:   "exports",
	Short: "List all workspace exports",
	Run: func(cmd *cobra.Command, args []string) {
		client, _ := mustClient()
		exports, err := client.ListExports()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}
		if len(exports) == 0 {
			fmt.Println("No exports found.")
			return
		}
		w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
		fmt.Fprintln(w, "TASK ID\tWORKSPACE\tSTATUS\tCREATED\tDOWNLOAD URL")
		for _, e := range exports {
			created := e.CreatedAt
			if len(created) > 16 {
				created = created[:16]
			}
			url := e.DownloadURL
			if url == "" && e.Error != "" {
				url = "ERROR: " + e.Error
			}
			fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", e.TaskID, e.WorkspaceName, e.Status, created, url)
		}
		w.Flush()
	},
}
