package db

import "fmt"

// Listener is a database listener record.
type Listener struct {
	ID             int64
	Addr           string
	ProxyProtocol  bool
	MaxConnections int64
}

// ListListeners returns all listeners.
func (s *Store) ListListeners() ([]Listener, error) {
	rows, err := s.db.Query("SELECT id, addr, proxy_protocol, max_connections FROM listeners ORDER BY id")
	if err != nil {
		return nil, fmt.Errorf("querying listeners: %w", err)
	}
	defer rows.Close()

	var listeners []Listener
	for rows.Next() {
		var l Listener
		if err := rows.Scan(&l.ID, &l.Addr, &l.ProxyProtocol, &l.MaxConnections); err != nil {
			return nil, fmt.Errorf("scanning listener: %w", err)
		}
		listeners = append(listeners, l)
	}
	return listeners, rows.Err()
}

// CreateListener inserts a listener and returns its ID.
func (s *Store) CreateListener(addr string, proxyProtocol bool, maxConnections int64) (int64, error) {
	result, err := s.db.Exec(
		"INSERT INTO listeners (addr, proxy_protocol, max_connections) VALUES (?, ?, ?)",
		addr, proxyProtocol, maxConnections,
	)
	if err != nil {
		return 0, fmt.Errorf("inserting listener: %w", err)
	}
	return result.LastInsertId()
}

// DeleteListener deletes a listener by ID. Routes are cascade-deleted.
func (s *Store) DeleteListener(id int64) error {
	result, err := s.db.Exec("DELETE FROM listeners WHERE id = ?", id)
	if err != nil {
		return fmt.Errorf("deleting listener: %w", err)
	}
	n, _ := result.RowsAffected()
	if n == 0 {
		return fmt.Errorf("listener %d not found", id)
	}
	return nil
}

// GetListenerByAddr returns a listener by its address.
func (s *Store) GetListenerByAddr(addr string) (Listener, error) {
	var l Listener
	err := s.db.QueryRow("SELECT id, addr, proxy_protocol, max_connections FROM listeners WHERE addr = ?", addr).
		Scan(&l.ID, &l.Addr, &l.ProxyProtocol, &l.MaxConnections)
	if err != nil {
		return Listener{}, fmt.Errorf("querying listener by addr %q: %w", addr, err)
	}
	return l, nil
}

// UpdateListenerMaxConns updates the max_connections for a listener.
func (s *Store) UpdateListenerMaxConns(listenerID int64, maxConns int64) error {
	result, err := s.db.Exec(
		"UPDATE listeners SET max_connections = ? WHERE id = ?",
		maxConns, listenerID,
	)
	if err != nil {
		return fmt.Errorf("updating max_connections: %w", err)
	}
	n, _ := result.RowsAffected()
	if n == 0 {
		return fmt.Errorf("listener %d not found", listenerID)
	}
	return nil
}
