package ssh

import (
	"fmt"
	"io"

	"golang.org/x/crypto/ssh"
)

// Client wraps the SSH connection
type Client struct {
	config  *ssh.ClientConfig
	address string
	conn    *ssh.Client
}

// Config contains SSH connection parameters
type Config struct {
	Host     string
	Port     int
	User     string
	Password string // TODO: Add key-based auth support
}

// NewClient creates a new SSH client
func NewClient(cfg Config) *Client {
	config := &ssh.ClientConfig{
		User: cfg.User,
		Auth: []ssh.AuthMethod{
			ssh.Password(cfg.Password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // TODO: Implement proper host key verification
	}

	return &Client{
		config:  config,
		address: fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
	}
}

// Connect establishes the SSH connection
func (c *Client) Connect() error {
	conn, err := ssh.Dial("tcp", c.address, c.config)
	if err != nil {
		return fmt.Errorf("failed to connect: %w", err)
	}
	c.conn = conn
	return nil
}

// Close closes the SSH connection
func (c *Client) Close() error {
	if c.conn != nil {
		return c.conn.Close()
	}
	return nil
}

// RunCommand runs a command and returns stdout
func (c *Client) RunCommand(cmd string) (string, error) {
	session, err := c.conn.NewSession()
	if err != nil {
		return "", fmt.Errorf("failed to create session: %w", err)
	}
	defer session.Close()

	output, err := session.CombinedOutput(cmd)
	if err != nil {
		return string(output), fmt.Errorf("command failed: %w", err)
	}
	return string(output), nil
}

// StreamCommand runs a command and streams stdout to a writer
func (c *Client) StreamCommand(cmd string, stdout io.Writer, stderr io.Writer) error {
	session, err := c.conn.NewSession()
	if err != nil {
		return fmt.Errorf("failed to create session: %w", err)
	}
	defer session.Close()

	session.Stdout = stdout
	session.Stderr = stderr

	if err := session.Run(cmd); err != nil {
		return fmt.Errorf("command failed: %w", err)
	}
	return nil
}

// StartCommand starts a command and returns pipes for streaming
func (c *Client) StartCommand(cmd string) (io.Reader, io.Reader, func() error, error) {
	session, err := c.conn.NewSession()
	if err != nil {
		return nil, nil, nil, fmt.Errorf("failed to create session: %w", err)
	}

	stdout, err := session.StdoutPipe()
	if err != nil {
		session.Close()
		return nil, nil, nil, fmt.Errorf("failed to get stdout: %w", err)
	}

	stderr, err := session.StderrPipe()
	if err != nil {
		session.Close()
		return nil, nil, nil, fmt.Errorf("failed to get stderr: %w", err)
	}

	if err := session.Start(cmd); err != nil {
		session.Close()
		return nil, nil, nil, fmt.Errorf("failed to start command: %w", err)
	}

	cleanup := func() error {
		session.Signal(ssh.SIGTERM)
		return session.Close()
	}

	return stdout, stderr, cleanup, nil
}
