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

// Package cli provides the account command.
package cli

import (
	"fmt"

	"github.com/spf13/cobra"
)

// AccountPayOptions contains options for the account pay subcommand.
type AccountPayOptions struct {
	Credits float64
}

// newAccountCommand creates the account command.
func (c *CLI) newAccountCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "account",
		Short: "Manage account",
		Long: `View and manage your Private Archive account.

Includes account information, credits, and payment history.`,
		Example: `  # Show account info
  privatebackup account

  # Create payment
  privatebackup account pay --credits 5

  # Show payment history
  privatebackup account payments`,
		RunE: func(cmd *cobra.Command, args []string) error {
			return c.runAccountInfo()
		},
	}

	// Add subcommands
	cmd.AddCommand(c.newAccountPayCommand())
	cmd.AddCommand(c.newAccountPaymentsCommand())

	return cmd
}

// runAccountInfo shows account information.
func (c *CLI) runAccountInfo() 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()

	account, err := c.client.Account(ctx)
	if err != nil {
		c.renderer.Error("No account configured")
		c.renderer.Info("Run 'privatebackup init' to create an account, or")
		c.renderer.Info("Run 'privatebackup restore-account --key-file <path>' to restore one.")
		return err
	}

	c.renderer.Output(account, func() {
		c.renderer.Section("Account Information")
		c.renderer.KeyValue("Certificate Hash", truncateHash(account.CertHash))
		c.renderer.KeyValue("Status", account.Status)
		c.renderer.KeyValue("Registered", formatDate(account.RegisteredAt))
		c.renderer.Newline()

		c.renderer.Section("Credits")
		c.renderer.KeyValue("Balance", fmt.Sprintf("%.2f credits", account.CreditsRemaining))
		c.renderer.KeyValue("Value", fmt.Sprintf("$%.2f (at $9.99/credit)", account.CreditsRemaining*9.99))
		c.renderer.Newline()

		c.renderer.Section("Storage Rates")
		c.renderer.KeyValue("Storage", "1 credit/TB/month ($9.99)")
		c.renderer.KeyValue("Retrieval", "Free (up to 2× storage/month)")
		c.renderer.Newline()

		c.renderer.Section("Payment Address")
		c.renderer.Info("Send Monero (XMR) to:")
		// In reality, we'd get the payment address from the backend
		c.renderer.Printf("  (Payment address would be shown here)\n")
		c.renderer.Newline()
		c.renderer.Info("Use 'privatebackup account pay --credits <n>' to create a payment intent.")
	})

	return nil
}

// newAccountPayCommand creates the account pay subcommand.
func (c *CLI) newAccountPayCommand() *cobra.Command {
	opts := &AccountPayOptions{}

	cmd := &cobra.Command{
		Use:   "pay",
		Short: "Create payment to add credits",
		Long: `Create a payment intent to add credits to your account.

This generates a payment address with a locked exchange rate
that's valid for 30 minutes.`,
		Example: `  # Create payment for 5 credits
  privatebackup account pay --credits 5`,
		RunE: func(cmd *cobra.Command, args []string) error {
			return c.runAccountPay(opts)
		},
	}

	flags := cmd.Flags()
	flags.Float64Var(&opts.Credits, "credits", 0, "Number of credits to purchase (required)")

	_ = cmd.MarkFlagRequired("credits")

	return cmd
}

// runAccountPay creates a payment intent.
func (c *CLI) runAccountPay(opts *AccountPayOptions) error {
	if opts.Credits <= 0 {
		return fmt.Errorf("credits must be greater than 0")
	}

	// Check backend connection
	if err := c.checkBackendConnection(); err != nil {
		return err
	}

	c.renderer.Info(fmt.Sprintf("Creating payment intent for %.1f credits...", opts.Credits))
	c.renderer.Newline()

	// In reality, we'd call the backend to create a payment intent
	// and get the XMR amount, rate, and address

	price := opts.Credits * 9.99
	xmrRate := 150.05 // Mock rate
	xmrAmount := price / xmrRate

	c.renderer.Section("Payment Details")
	c.renderer.KeyValue("Credits", fmt.Sprintf("%.1f", opts.Credits))
	c.renderer.KeyValue("Price", fmt.Sprintf("$%.2f USD", price))
	c.renderer.KeyValue("XMR Amount", fmt.Sprintf("%.4f XMR", xmrAmount))
	c.renderer.KeyValue("XMR Rate", fmt.Sprintf("$%.2f/XMR", xmrRate))
	c.renderer.KeyValue("Expires", "30 minutes")
	c.renderer.Newline()

	c.renderer.Info(fmt.Sprintf("Send exactly %.4f XMR to:", xmrAmount))
	c.renderer.Printf("  (Payment address would be shown here)\n")
	c.renderer.Newline()

	// In reality, we'd show a QR code if the terminal supports it
	c.renderer.Info("Waiting for payment... (Ctrl+C to cancel)")
	c.renderer.Newline()

	// In a real implementation, we'd poll for payment confirmation
	c.renderer.Info("Payment confirmation would be monitored here.")

	return nil
}

// newAccountPaymentsCommand creates the account payments subcommand.
func (c *CLI) newAccountPaymentsCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:     "payments",
		Short:   "Show payment history",
		Long:    `Display your payment history.`,
		Example: `  privatebackup account payments`,
		RunE: func(cmd *cobra.Command, args []string) error {
			return c.runAccountPayments()
		},
	}

	return cmd
}

// runAccountPayments shows payment history.
func (c *CLI) runAccountPayments() error {
	// Check backend connection
	if err := c.checkBackendConnection(); err != nil {
		return err
	}

	c.renderer.Section("Payment History")
	c.renderer.Newline()

	// In reality, we'd fetch payment history from the backend
	c.renderer.Info("No payments found")
	c.renderer.Newline()
	c.renderer.Info("Use 'privatebackup account pay --credits <n>' to make a payment.")

	return nil
}
