package store

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

// PollState tracks the last polled tag for a stage, enabling the poller to
// detect new tags since the previous poll cycle.
type PollState struct {
	StageID    string `json:"stage_id"`
	LastTag    string `json:"last_tag"`
	LastPolled string `json:"last_polled"`
}

// GetPollState returns the poll state for a given stage.
func (s *Store) GetPollState(stageID string) (PollState, error) {
	var ps PollState
	err := s.db.QueryRow(
		`SELECT stage_id, last_tag, last_polled FROM poll_states WHERE stage_id = ?`,
		stageID,
	).Scan(&ps.StageID, &ps.LastTag, &ps.LastPolled)
	if errors.Is(err, sql.ErrNoRows) {
		return PollState{}, fmt.Errorf("poll state for stage %s: %w", stageID, ErrNotFound)
	}
	if err != nil {
		return PollState{}, fmt.Errorf("query poll state: %w", err)
	}
	return ps, nil
}

// UpsertPollState inserts or updates the poll state for a stage.
func (s *Store) UpsertPollState(ps PollState) error {
	_, err := s.db.Exec(
		`INSERT INTO poll_states (stage_id, last_tag, last_polled)
		 VALUES (?, ?, ?)
		 ON CONFLICT(stage_id) DO UPDATE SET last_tag=excluded.last_tag, last_polled=excluded.last_polled`,
		ps.StageID, ps.LastTag, ps.LastPolled,
	)
	if err != nil {
		return fmt.Errorf("upsert poll state: %w", err)
	}
	return nil
}

// DeletePollState removes the poll state for a stage.
func (s *Store) DeletePollState(stageID string) error {
	_, err := s.db.Exec(`DELETE FROM poll_states WHERE stage_id = ?`, stageID)
	if err != nil {
		return fmt.Errorf("delete poll state: %w", err)
	}
	return nil
}

// GetAllPollStates returns all poll states, ordered by last_polled descending.
func (s *Store) GetAllPollStates() ([]PollState, error) {
	rows, err := s.db.Query(
		`SELECT stage_id, last_tag, last_polled FROM poll_states ORDER BY last_polled DESC`,
	)
	if err != nil {
		return nil, fmt.Errorf("query poll states: %w", err)
	}
	defer rows.Close()

	states := []PollState{}
	for rows.Next() {
		var ps PollState
		if err := rows.Scan(&ps.StageID, &ps.LastTag, &ps.LastPolled); err != nil {
			return nil, fmt.Errorf("scan poll state: %w", err)
		}
		states = append(states, ps)
	}
	return states, rows.Err()
}
