package store

import (
	"database/sql"
	"errors"
	"fmt"

	"github.com/google/uuid"
)

// CreateStandaloneProxy inserts a new standalone proxy record.
func (s *Store) CreateStandaloneProxy(p StandaloneProxy) (StandaloneProxy, error) {
	p.ID = uuid.New().String()
	p.CreatedAt = Now()
	p.UpdatedAt = p.CreatedAt

	if p.HealthStatus == "" {
		p.HealthStatus = "unknown"
	}

	_, err := s.db.Exec(
		`INSERT INTO standalone_proxies (id, domain, destination_url, destination_port, ssl_certificate_id, npm_proxy_id, health_status, health_checked_at, created_at, updated_at)
		 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
		p.ID, p.Domain, p.DestinationURL, p.DestinationPort, p.SSLCertificateID,
		p.NpmProxyID, p.HealthStatus, p.HealthCheckedAt, p.CreatedAt, p.UpdatedAt,
	)
	if err != nil {
		return StandaloneProxy{}, fmt.Errorf("insert standalone proxy: %w", err)
	}
	return p, nil
}

// GetStandaloneProxy returns a standalone proxy by ID.
func (s *Store) GetStandaloneProxy(id string) (StandaloneProxy, error) {
	var p StandaloneProxy
	err := s.db.QueryRow(
		`SELECT id, domain, destination_url, destination_port, ssl_certificate_id, npm_proxy_id, health_status, health_checked_at, created_at, updated_at
		 FROM standalone_proxies WHERE id = ?`, id,
	).Scan(&p.ID, &p.Domain, &p.DestinationURL, &p.DestinationPort, &p.SSLCertificateID,
		&p.NpmProxyID, &p.HealthStatus, &p.HealthCheckedAt, &p.CreatedAt, &p.UpdatedAt)
	if errors.Is(err, sql.ErrNoRows) {
		return StandaloneProxy{}, fmt.Errorf("standalone proxy %s: %w", id, ErrNotFound)
	}
	if err != nil {
		return StandaloneProxy{}, fmt.Errorf("query standalone proxy: %w", err)
	}
	return p, nil
}

// ListStandaloneProxies returns all standalone proxy records ordered by creation time.
func (s *Store) ListStandaloneProxies() ([]StandaloneProxy, error) {
	rows, err := s.db.Query(
		`SELECT id, domain, destination_url, destination_port, ssl_certificate_id, npm_proxy_id, health_status, health_checked_at, created_at, updated_at
		 FROM standalone_proxies ORDER BY created_at DESC`,
	)
	if err != nil {
		return nil, fmt.Errorf("query standalone proxies: %w", err)
	}
	defer rows.Close()

	proxies := []StandaloneProxy{}
	for rows.Next() {
		var p StandaloneProxy
		if err := rows.Scan(&p.ID, &p.Domain, &p.DestinationURL, &p.DestinationPort, &p.SSLCertificateID,
			&p.NpmProxyID, &p.HealthStatus, &p.HealthCheckedAt, &p.CreatedAt, &p.UpdatedAt); err != nil {
			return nil, fmt.Errorf("scan standalone proxy: %w", err)
		}
		proxies = append(proxies, p)
	}
	return proxies, rows.Err()
}

// UpdateStandaloneProxy updates an existing standalone proxy's mutable fields.
func (s *Store) UpdateStandaloneProxy(p StandaloneProxy) error {
	p.UpdatedAt = Now()
	result, err := s.db.Exec(
		`UPDATE standalone_proxies SET domain=?, destination_url=?, destination_port=?, ssl_certificate_id=?, npm_proxy_id=?, health_status=?, health_checked_at=?, updated_at=?
		 WHERE id=?`,
		p.Domain, p.DestinationURL, p.DestinationPort, p.SSLCertificateID,
		p.NpmProxyID, p.HealthStatus, p.HealthCheckedAt, p.UpdatedAt, p.ID,
	)
	if err != nil {
		return fmt.Errorf("update standalone proxy: %w", err)
	}
	n, _ := result.RowsAffected()
	if n == 0 {
		return fmt.Errorf("standalone proxy %s: %w", p.ID, ErrNotFound)
	}
	return nil
}

// DeleteStandaloneProxy removes a standalone proxy by ID.
func (s *Store) DeleteStandaloneProxy(id string) error {
	result, err := s.db.Exec(`DELETE FROM standalone_proxies WHERE id = ?`, id)
	if err != nil {
		return fmt.Errorf("delete standalone proxy: %w", err)
	}
	n, _ := result.RowsAffected()
	if n == 0 {
		return fmt.Errorf("standalone proxy %s: %w", id, ErrNotFound)
	}
	return nil
}

// UpdateProxyHealth updates the health status and check timestamp for a standalone proxy.
func (s *Store) UpdateProxyHealth(id string, status string) error {
	ts := Now()
	result, err := s.db.Exec(
		`UPDATE standalone_proxies SET health_status=?, health_checked_at=?, updated_at=? WHERE id=?`,
		status, ts, ts, id,
	)
	if err != nil {
		return fmt.Errorf("update proxy health: %w", err)
	}
	n, _ := result.RowsAffected()
	if n == 0 {
		return fmt.Errorf("standalone proxy %s: %w", id, ErrNotFound)
	}
	return nil
}
