package data

import (
	"context"
	"database/sql"
	"time"

	"github.com/lib/pq"
)

type ParlWatcherModel struct {
	DB *sql.DB
}

// FilterNew returns only the numbers from the input that are not yet recorded.
func (m ParlWatcherModel) FilterNew(numbers []string) ([]string, error) {
	query := `
		SELECT unnest($1::text[]) AS num
		EXCEPT
		SELECT number FROM parl_notified_votes`

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	rows, err := m.DB.QueryContext(ctx, query, pq.Array(numbers))
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var result []string
	for rows.Next() {
		var n string
		if err := rows.Scan(&n); err != nil {
			return nil, err
		}
		result = append(result, n)
	}
	return result, rows.Err()
}

// MarkNotified records the given numbers so they are not notified again.
func (m ParlWatcherModel) MarkNotified(numbers []string) error {
	query := `
		INSERT INTO parl_notified_votes (number)
		SELECT unnest($1::text[])
		ON CONFLICT (number) DO NOTHING`

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	_, err := m.DB.ExecContext(ctx, query, pq.Array(numbers))
	return err
}

// GetAllNotifiedNumbers returns every number that has already been notified.
// Unused in the hot path but useful for debugging/admin.
func (m ParlWatcherModel) GetAllNotifiedNumbers() ([]string, error) {
	query := `SELECT number FROM parl_notified_votes ORDER BY notified_at DESC`

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	rows, err := m.DB.QueryContext(ctx, query)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var result []string
	for rows.Next() {
		var n string
		if err := rows.Scan(&n); err != nil {
			return nil, err
		}
		result = append(result, n)
	}
	return result, rows.Err()
}

// Ensure ParlWatcherModel satisfies the interface even if DB is nil (e.g. in tests).
var _ = sql.ErrNoRows
