package proxypool

import (
	"math/rand"
	"sync"
	"time"
)

type Entry struct {
	URL string

	mu            sync.Mutex
	failures      int
	cooldownUntil time.Time
}

type Pool struct {
	entries []*Entry
	idx     int
	mu      sync.Mutex
}

// New builds a proxy pool with health tracking. A proxy URL is handed to the
// HTTP clients (they own their own connections); the pool only decides which
// proxy to use next.
func New(proxyURLs []string) *Pool {
	p := &Pool{}
	for _, u := range proxyURLs {
		p.entries = append(p.entries, &Entry{URL: u})
	}
	return p
}

// Next returns the next healthy proxy entry using round-robin, or nil when no
// proxies are configured (direct connection).
func (p *Pool) Next() *Entry {
	if len(p.entries) == 0 {
		return nil
	}
	p.mu.Lock()
	defer p.mu.Unlock()
	now := time.Now()
	for i := 0; i < len(p.entries); i++ {
		e := p.entries[p.idx%len(p.entries)]
		p.idx++
		e.mu.Lock()
		cool := now.Before(e.cooldownUntil)
		e.mu.Unlock()
		if !cool {
			return e
		}
	}
	return p.entries[rand.Intn(len(p.entries))]
}

func (e *Entry) ReportFailure(cooldown time.Duration) {
	e.mu.Lock()
	defer e.mu.Unlock()
	e.failures++
	if e.failures >= 3 {
		e.cooldownUntil = time.Now().Add(cooldown)
		e.failures = 0
	}
}

func (e *Entry) ReportSuccess() {
	e.mu.Lock()
	defer e.mu.Unlock()
	e.failures = 0
}

func (p *Pool) Size() int {
	return len(p.entries)
}
