package postgres

import (
	"context"
	"database/sql"

	"switchboard-core/models"
)

// ── DependencyStore ────────────────────────

type DependencyStore struct{}

func NewDependencyStore() *DependencyStore { return &DependencyStore{} }

const depCols = `consumer_id, library_id, version_spec, resolved_ver`

func (s *DependencyStore) Create(ctx context.Context, dep *models.ExtDependency) error {
	_, err := DB.ExecContext(ctx, `
		INSERT INTO ext_dependencies (consumer_id, library_id, version_spec, resolved_ver)
		VALUES ($1, $2, $3, $4)
		ON CONFLICT (consumer_id, library_id) DO UPDATE
		SET version_spec = EXCLUDED.version_spec, resolved_ver = EXCLUDED.resolved_ver`,
		dep.ConsumerID, dep.LibraryID, dep.VersionSpec, dep.ResolvedVer,
	)
	return err
}

func (s *DependencyStore) Delete(ctx context.Context, consumerID, libraryID string) error {
	_, err := DB.ExecContext(ctx,
		`DELETE FROM ext_dependencies WHERE consumer_id = $1 AND library_id = $2`,
		consumerID, libraryID)
	return err
}

func (s *DependencyStore) DeleteAllForConsumer(ctx context.Context, consumerID string) error {
	_, err := DB.ExecContext(ctx,
		`DELETE FROM ext_dependencies WHERE consumer_id = $1`, consumerID)
	return err
}

func (s *DependencyStore) ListByConsumer(ctx context.Context, consumerID string) ([]models.ExtDependency, error) {
	rows, err := DB.QueryContext(ctx,
		`SELECT `+depCols+` FROM ext_dependencies WHERE consumer_id = $1 ORDER BY library_id`,
		consumerID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return scanDependencies(rows)
}

func (s *DependencyStore) ListByLibrary(ctx context.Context, libraryID string) ([]models.ExtDependency, error) {
	rows, err := DB.QueryContext(ctx,
		`SELECT `+depCols+` FROM ext_dependencies WHERE library_id = $1 ORDER BY consumer_id`,
		libraryID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return scanDependencies(rows)
}

func (s *DependencyStore) ListAll(ctx context.Context) ([]models.ExtDependency, error) {
	rows, err := DB.QueryContext(ctx,
		`SELECT `+depCols+` FROM ext_dependencies ORDER BY consumer_id, library_id`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return scanDependencies(rows)
}

func (s *DependencyStore) HasConsumers(ctx context.Context, libraryID string) (bool, error) {
	var exists bool
	err := DB.QueryRowContext(ctx,
		`SELECT EXISTS(SELECT 1 FROM ext_dependencies WHERE library_id = $1)`,
		libraryID).Scan(&exists)
	return exists, err
}

// ── Internal ───────────────────────────────────────

func scanDependencies(rows *sql.Rows) ([]models.ExtDependency, error) {
	var result []models.ExtDependency
	for rows.Next() {
		var d models.ExtDependency
		err := rows.Scan(&d.ConsumerID, &d.LibraryID, &d.VersionSpec, &d.ResolvedVer)
		if err != nil {
			return nil, err
		}
		result = append(result, d)
	}
	return result, rows.Err()
}
