package intelligence

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

// HRRisk is one (torrent, tracker) pair's distance to hit-and-run trouble.
type HRRisk struct {
	InfoHash                      string    `json:"info_hash"`
	TorrentName                   string    `json:"torrent_name"`
	TrackerID                     string    `json:"tracker_id"`
	SeedTimeRequiredSeconds       int64     `json:"seed_time_required_seconds"`
	SeedTimeAccumulatedSeconds    int64     `json:"seed_time_accumulated_seconds"`
	HoursUntilRequirement         float64   `json:"hours_until_requirement"`
	RiskAt                        time.Time `json:"risk_at"`
}

// FindAtRisk returns torrents whose remaining seed-time-required is below
// `withinHours`. The seed_time_required column is populated by Phase 11's
// tracker rule corpus; until then it's NULL and this function falls back
// to a configurable per-call default.
//
// Phase 7 ships a naive accumulator: `seed_time_accumulated = now - first_seen_at`.
// Phase 9's tqm integration may publish a more precise per-tracker
// accumulator; the column can be updated independently.
func FindAtRisk(ctx context.Context, db *sql.DB, withinHours float64, defaultRequiredSeconds int64) ([]HRRisk, error) {
	if withinHours <= 0 {
		withinHours = 24
	}
	if defaultRequiredSeconds <= 0 {
		defaultRequiredSeconds = 432000 // 120h, a common default per Appendix E
	}
	now := time.Now()
	cutoffSeconds := int64(withinHours * 3600)

	rows, err := db.QueryContext(ctx, `
		SELECT tt.info_hash, COALESCE(t.name, ''), tt.tracker_id,
		       COALESCE(tt.seed_time_required_seconds, ?) AS required,
		       (? - COALESCE(t.first_seen_at, ?)) AS accumulated
		FROM torrent_trackers tt
		LEFT JOIN torrents t ON t.info_hash = tt.info_hash
		WHERE COALESCE(t.deleted_at, 0) = 0
	`, defaultRequiredSeconds, now.Unix(), now.Unix())
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var out []HRRisk
	for rows.Next() {
		var (
			hash, name, trackerID string
			required, accumulated int64
		)
		if err := rows.Scan(&hash, &name, &trackerID, &required, &accumulated); err != nil {
			return nil, err
		}
		remaining := required - accumulated
		if remaining > cutoffSeconds {
			continue // not yet at risk
		}
		if remaining < 0 {
			continue // already past requirement; not at risk
		}
		hours := float64(remaining) / 3600.0
		out = append(out, HRRisk{
			InfoHash:                   hash,
			TorrentName:                name,
			TrackerID:                  trackerID,
			SeedTimeRequiredSeconds:    required,
			SeedTimeAccumulatedSeconds: accumulated,
			HoursUntilRequirement:      hours,
			RiskAt:                     now.Add(time.Duration(remaining) * time.Second),
		})
	}
	return out, rows.Err()
}
