package store

import (
	"context"
	"errors"
	"fmt"

	"github.com/jackc/pgx/v5"
)

// SetAutoSummarize sets the user's auto/manual summarization mode. TRUE =
// automatic (every new video is summarized by `tapir run`); FALSE = manual (the
// user queues videos individually). Per-user, not global (ADR-012). Scoped via
// withUser, so RLS confines the UPDATE to the calling user's own row.
func (s *Store) SetAutoSummarize(ctx context.Context, userID string, enabled bool) error {
	return s.withUser(ctx, userID, func(tx pgx.Tx) error {
		// Ensure the row exists (FK/identity target) before the UPDATE — mirrors
		// the Deliver/UpsertVideo paths, so toggling mode works even before the
		// first summary lands.
		if _, err := tx.Exec(ctx,
			`INSERT INTO users (id) VALUES ($1) ON CONFLICT (id) DO NOTHING`,
			userID); err != nil {
			return fmt.Errorf("store: upsert user: %w", err)
		}
		if _, err := tx.Exec(ctx,
			`UPDATE users SET auto_summarize = $1 WHERE id = $2`, enabled, userID); err != nil {
			return fmt.Errorf("store: set auto summarize: %w", err)
		}
		return nil
	})
}

// GetAutoSummarize reports the user's summarization mode (TRUE = automatic). An
// absent user row reads as FALSE (manual), the safe default. Scoped via withUser.
func (s *Store) GetAutoSummarize(ctx context.Context, userID string) (bool, error) {
	var enabled bool
	if err := s.withUser(ctx, userID, func(tx pgx.Tx) error {
		err := tx.QueryRow(ctx,
			`SELECT auto_summarize FROM users WHERE id = $1`, userID).Scan(&enabled)
		if errors.Is(err, pgx.ErrNoRows) {
			enabled = false
			return nil
		}
		return err
	}); err != nil {
		return false, fmt.Errorf("store: get auto summarize: %w", err)
	}
	return enabled, nil
}

// RequestSummarize queues a single video for manual summarization by setting its
// summarize_requested flag. The next `tapir run` picks it up and clears the flag.
// Returns ErrNotFound when the video does not exist or is not owned by the user
// (RLS hides another user's row, so the UPDATE matches zero rows). Scoped via
// withUser.
func (s *Store) RequestSummarize(ctx context.Context, userID, videoID string) error {
	return s.withUser(ctx, userID, func(tx pgx.Tx) error {
		ct, err := tx.Exec(ctx,
			`UPDATE videos SET summarize_requested = TRUE WHERE id = $1`, videoID)
		if err != nil {
			return fmt.Errorf("store: request summarize: %w", err)
		}
		if ct.RowsAffected() == 0 {
			return ErrNotFound
		}
		return nil
	})
}

// RequestedVideoIDs returns the set of the user's video ids currently flagged for
// manual summarization. The run loop loads it once per pass (mirroring
// SeenVideoIDs) to decide which discovered videos to process in manual mode.
// Scoped by user_id.
func (s *Store) RequestedVideoIDs(ctx context.Context, userID string) (map[string]bool, error) {
	requested := make(map[string]bool)
	if err := s.withUser(ctx, userID, func(tx pgx.Tx) error {
		rows, err := tx.Query(ctx,
			`SELECT id FROM videos WHERE user_id = $1 AND summarize_requested = TRUE`, userID)
		if err != nil {
			return fmt.Errorf("store: requested video ids: %w", err)
		}
		defer rows.Close()

		for rows.Next() {
			var id string
			if err := rows.Scan(&id); err != nil {
				return fmt.Errorf("store: scan requested id: %w", err)
			}
			requested[id] = true
		}
		if err := rows.Err(); err != nil {
			return fmt.Errorf("store: iterate requested ids: %w", err)
		}
		return nil
	}); err != nil {
		return nil, err
	}
	return requested, nil
}

// ClearSummarizeRequested resets a video's manual queue flag, called by the run
// loop after a queued video is successfully summarized so it is not re-processed
// and the list view drops the "Queued" chip. Scoped via withUser.
func (s *Store) ClearSummarizeRequested(ctx context.Context, userID, videoID string) error {
	return s.withUser(ctx, userID, func(tx pgx.Tx) error {
		if _, err := tx.Exec(ctx,
			`UPDATE videos SET summarize_requested = FALSE WHERE id = $1`, videoID); err != nil {
			return fmt.Errorf("store: clear summarize requested: %w", err)
		}
		return nil
	})
}
