// SPDX-License-Identifier: GPL-3.0-or-later

// Package cli provides the mode command for switching between simple and advanced modes.
package cli

import (
	"fmt"
	"strings"

	"github.com/privatebackup/client-frontend-unix/internal/client"
	"github.com/spf13/cobra"
)

// newModeCommand creates the mode command.
func (c *CLI) newModeCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "mode",
		Short: "View or change operating mode",
		Long: `View or switch between simple and advanced operating modes.

Simple mode (default):
  - Automatic retention: keeps snapshots for 7 days, 4 weeks, 12 months, 10 years
  - Automatic pruning after each backup
  - Simplified commands
  - Best for most users

Advanced mode:
  - Manual retention management
  - Full access to restic commands
  - No automatic pruning
  - For users who need fine-grained control`,
		Example: `  # Show current mode
  privatebackup mode

  # Switch to advanced mode
  privatebackup mode advanced

  # Switch to simple mode
  privatebackup mode simple`,
		RunE: func(cmd *cobra.Command, args []string) error {
			return c.runModeShow()
		},
	}

	// Add subcommands
	cmd.AddCommand(c.newModeSimpleCommand())
	cmd.AddCommand(c.newModeAdvancedCommand())

	return cmd
}

// runModeShow displays the current operating mode.
func (c *CLI) runModeShow() error {
	// Check backend connection
	if err := c.checkBackendConnection(); err != nil {
		if IsBackendNotRunning(err) {
			c.renderer.Error("Cannot connect to backend daemon")
			c.renderer.Info("Start it with: privatebackup daemon start")
			return err
		}
		return fmt.Errorf("backend error: %w", err)
	}

	ctx, cancel := c.GetContext()
	defer cancel()

	resp, err := c.client.GetMode(ctx)
	if err != nil {
		return fmt.Errorf("failed to get mode: %w", err)
	}

	c.renderer.Output(resp, func() {
		c.renderer.Heading("Operating Mode")
		c.renderer.Newline()

		modeDisplay := "Simple"
		if resp.Mode == "advanced" {
			modeDisplay = "Advanced"
		}

		c.renderer.KeyValue("Current mode", modeDisplay)
		c.renderer.Newline()
		c.renderer.Info(resp.Description)
		c.renderer.Newline()

		if len(resp.Features) > 0 {
			c.renderer.Section("Features")
			for _, feature := range resp.Features {
				c.renderer.Printf("  • %s\n", feature)
			}
		}
		c.renderer.Newline()

		if resp.Mode == "simple" {
			c.renderer.Info("Switch to advanced mode: privatebackup mode advanced")
		} else {
			c.renderer.Info("Switch to simple mode: privatebackup mode simple")
		}
	})

	return nil
}

// newModeSimpleCommand creates the mode simple subcommand.
func (c *CLI) newModeSimpleCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "simple",
		Short: "Switch to simple mode",
		Long: `Switch to simple mode with automatic retention and pruning.

Simple mode provides:
  - Automatic retention: keeps snapshots for 7 days, 4 weeks, 12 months, 10 years
  - Automatic pruning after each backup
  - Simplified commands optimized for common use cases`,
		RunE: func(cmd *cobra.Command, args []string) error {
			return c.runModeSwitch("simple")
		},
	}

	return cmd
}

// newModeAdvancedCommand creates the mode advanced subcommand.
func (c *CLI) newModeAdvancedCommand() *cobra.Command {
	var skipConfirmation bool

	cmd := &cobra.Command{
		Use:   "advanced",
		Short: "Switch to advanced mode",
		Long: `Switch to advanced mode for manual control.

Advanced mode provides:
  - Manual retention management (you control when to prune)
  - Full access to restic forget and prune commands
  - No automatic pruning

WARNING: In advanced mode, you are responsible for managing snapshot
retention. Without regular pruning, storage usage will grow indefinitely.`,
		RunE: func(cmd *cobra.Command, args []string) error {
			return c.runModeSwitchAdvanced(skipConfirmation)
		},
	}

	cmd.Flags().BoolVar(&skipConfirmation, "yes", false, "Skip confirmation prompt (for automated testing)")

	return cmd
}

// runModeSwitch switches to the specified mode.
func (c *CLI) runModeSwitch(mode string) error {
	// Check backend connection
	if err := c.checkBackendConnection(); err != nil {
		if IsBackendNotRunning(err) {
			c.renderer.Error("Cannot connect to backend daemon")
			c.renderer.Info("Start it with: privatebackup daemon start")
			return err
		}
		return fmt.Errorf("backend error: %w", err)
	}

	ctx, cancel := c.GetContext()
	defer cancel()

	req := &client.ModeUpdateRequest{
		Mode:        mode,
		Acknowledge: mode != "advanced", // Simple mode doesn't need acknowledgment
	}

	resp, err := c.client.SwitchMode(ctx, req)
	if err != nil {
		return fmt.Errorf("failed to switch mode: %w", err)
	}

	modeDisplay := "Simple"
	if resp.Mode == "advanced" {
		modeDisplay = "Advanced"
	}

	c.renderer.Success(fmt.Sprintf("Switched to %s mode", modeDisplay))
	c.renderer.Newline()
	c.renderer.Info(resp.Description)

	return nil
}

// runModeSwitchAdvanced handles switching to advanced mode with confirmation.
func (c *CLI) runModeSwitchAdvanced(skipConfirmation bool) error {
	// Check backend connection
	if err := c.checkBackendConnection(); err != nil {
		if IsBackendNotRunning(err) {
			c.renderer.Error("Cannot connect to backend daemon")
			c.renderer.Info("Start it with: privatebackup daemon start")
			return err
		}
		return fmt.Errorf("backend error: %w", err)
	}

	// Skip confirmation if --yes flag is provided
	if !skipConfirmation {
		// Warn about advanced mode
		c.renderer.Heading("Warning: Switching to Advanced Mode")
		c.renderer.Newline()
		c.renderer.Info("In advanced mode, you are responsible for:")
		c.renderer.Printf("  • Running 'privatebackup forget' to manage retention\n")
		c.renderer.Printf("  • Running 'privatebackup check' to verify repository health\n")
		c.renderer.Printf("  • Monitoring storage usage\n")
		c.renderer.Newline()
		c.renderer.Info("Without regular pruning, storage usage will grow indefinitely.")
		c.renderer.Newline()

		// Get confirmation
		confirmPhrase := "I understand"
		c.renderer.Printf("Type '%s' to confirm: ", confirmPhrase)

		input, err := c.prompter.Input("")
		if err != nil {
			return fmt.Errorf("failed to read input: %w", err)
		}

		if strings.TrimSpace(input) != confirmPhrase {
			c.renderer.Error("Mode switch cancelled")
			return fmt.Errorf("confirmation not provided")
		}
	}

	ctx, cancel := c.GetContext()
	defer cancel()

	req := &client.ModeUpdateRequest{
		Mode:        "advanced",
		Acknowledge: true,
	}

	resp, err := c.client.SwitchMode(ctx, req)
	if err != nil {
		return fmt.Errorf("failed to switch mode: %w", err)
	}

	c.renderer.Success("Switched to Advanced mode")
	c.renderer.Newline()
	c.renderer.Info(resp.Description)

	return nil
}
