package db

import (
	"context"
	"database/sql"
	"errors"

	"github.com/bluesky-social/indigo/atproto/syntax"
)

func (d *DB) ListAllowedMembers() ([]syntax.DID, error) {
	rows, err := d.Query(`select did from members where blocked = 0`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var dids []syntax.DID
	for rows.Next() {
		var did syntax.DID
		if err := rows.Scan(&did); err != nil {
			return nil, err
		}
		dids = append(dids, did)
	}

	return dids, rows.Err()
}

// IsAllowedMember reports whether did is known and unblocked. Unknown DIDs get fallback.
func (d *DB) IsAllowedMember(ctx context.Context, did syntax.DID, fallback bool) (bool, error) {
	var blocked bool
	err := d.QueryRowContext(ctx, `select blocked from members where did = ?`, did).Scan(&blocked)
	if errors.Is(err, sql.ErrNoRows) {
		return fallback, nil
	}
	if err != nil {
		return false, err
	}
	return !blocked, nil
}

func (d *DB) AllowMember(ctx context.Context, did syntax.DID) error {
	return d.UpsertMember(ctx, did, false)
}

func (d *DB) BlockMember(ctx context.Context, did syntax.DID) error {
	return d.UpsertMember(ctx, did, true)
}

func (d *DB) UpsertMember(ctx context.Context, did syntax.DID, block bool) error {
	_, err := d.ExecContext(ctx, `
		insert into members (did, blocked) values (?, ?)
		on conflict(did) do update set blocked = excluded.blocked
	`, did, block)
	return err
}
