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

// Package cli provides the status command.
package cli

import (
	"fmt"
	"time"

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

// newStatusCommand creates the status command.
func (c *CLI) newStatusCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "status",
		Short: "Show backend and account status",
		Long: `Show the current status of the backend daemon, Tor connection,
server connection, and account information.`,
		Example: `  privatebackup status`,
		RunE: func(cmd *cobra.Command, args []string) error {
			return c.runStatus()
		},
	}

	return cmd
}

// runStatus executes the status command.
func (c *CLI) runStatus() error {
	ctx, cancel := c.GetContext()
	defer cancel()

	// Get backend status
	backendStatus, err := c.client.Status(ctx)
	if err != nil {
		c.renderer.Error("Cannot connect to backend daemon")
		c.renderer.Newline()
		c.renderer.Info("The Private Archive backend is not running.")
		c.renderer.Newline()
		c.renderer.Info("To start it:")
		c.renderer.Printf("  $ privatebackup daemon start\n")
		return err
	}

	// Get Tor status
	torStatus, err := c.client.TorStatus(ctx)
	if err != nil {
		torStatus = &client.TorStatusResponse{Connected: false}
	}

	// Get server status
	serverStatus, err := c.client.ServerStatus(ctx)
	if err != nil {
		serverStatus = &client.ServerStatusResponse{Connected: false}
	}

	// Get account info
	account, err := c.client.Account(ctx)
	if err != nil {
		account = nil
	}

	// Output as JSON if requested
	c.renderer.Output(map[string]interface{}{
		"backend": backendStatus,
		"tor":     torStatus,
		"server":  serverStatus,
		"account": account,
	}, func() {
		// Human-readable output
		c.renderer.Section("Backend Status")
		c.renderer.KeyValue("Version", backendStatus.Version)
		c.renderer.KeyValue("Status", c.renderer.Colors().Success(backendStatus.Status))
		c.renderer.KeyValue("Uptime", backendStatus.Uptime)
		c.renderer.Newline()

		c.renderer.Section("Tor Connection")
		if torStatus.Connected {
			c.renderer.KeyValue("Status", c.renderer.Colors().Success("Connected"))
			c.renderer.KeyValue("Bootstrap", fmt.Sprintf("%d%%", torStatus.BootstrapPct))
			c.renderer.KeyValue("Circuits", fmt.Sprintf("%d", torStatus.CircuitCount))
		} else {
			c.renderer.KeyValue("Status", c.renderer.Colors().Error("Disconnected"))
		}
		c.renderer.Newline()

		c.renderer.Section("Server Connection")
		if serverStatus.Connected {
			c.renderer.KeyValue("Status", c.renderer.Colors().Success("Reachable"))
			c.renderer.KeyValue("Last Contact", formatTimeAgo(serverStatus.LastContactAt))
		} else {
			c.renderer.KeyValue("Status", c.renderer.Colors().Error("Unreachable"))
		}
		c.renderer.Newline()

		if account != nil {
			c.renderer.Section("Account Status")
			c.renderer.KeyValue("Status", account.Status)
			c.renderer.KeyValue("Credits", fmt.Sprintf("%.2f ($%.2f)", account.CreditsRemaining, account.CreditsRemaining*9.99))
			c.renderer.Newline()

			c.renderer.Section("Storage Usage")
			c.renderer.KeyValue("Total Used", formatBytes(account.StorageUsedBytes))
			// In reality, we'd show hot/cold breakdown
			c.renderer.Newline()
		} else {
			c.renderer.Section("Account")
			c.renderer.Warning("No account configured")
			c.renderer.Info("Run 'privatebackup init' to create an account")
			c.renderer.Newline()
		}
	})

	return nil
}

// formatTimeAgo formats a time as "X ago".
func formatTimeAgo(t time.Time) string {
	if t.IsZero() {
		return "never"
	}

	duration := time.Since(t)

	if duration < time.Minute {
		return "just now"
	} else if duration < time.Hour {
		mins := int(duration.Minutes())
		if mins == 1 {
			return "1 minute ago"
		}
		return fmt.Sprintf("%d minutes ago", mins)
	} else if duration < 24*time.Hour {
		hours := int(duration.Hours())
		if hours == 1 {
			return "1 hour ago"
		}
		return fmt.Sprintf("%d hours ago", hours)
	} else {
		days := int(duration.Hours() / 24)
		if days == 1 {
			return "1 day ago"
		}
		return fmt.Sprintf("%d days ago", days)
	}
}
