package provider

import (
	"context"
	"sync"
	"time"
)

type RefreshStats struct {
	CollectorName string
	LastSuccess   time.Time
	LastError     string
	ErrorCount    uint64
}

type Refresher struct {
	collector Collector
	interval  time.Duration

	mu       sync.RWMutex
	snapshot Snapshot
	has      bool
	stats    RefreshStats
}

func NewRefresher(collector Collector, interval time.Duration) *Refresher {
	return &Refresher{
		collector: collector,
		interval:  interval,
		stats: RefreshStats{
			CollectorName: collector.Name(),
		},
	}
}

func (r *Refresher) Run(ctx context.Context) {
	_ = r.Refresh(ctx)
	ticker := time.NewTicker(r.interval)
	defer ticker.Stop()
	for {
		select {
		case <-ctx.Done():
			return
		case <-ticker.C:
			_ = r.Refresh(ctx)
		}
	}
}

func (r *Refresher) Refresh(ctx context.Context) error {
	snapshot, err := r.collector.Refresh(ctx)
	r.mu.Lock()
	defer r.mu.Unlock()
	if err != nil {
		r.stats.ErrorCount++
		r.stats.LastError = err.Error()
		return err
	}
	if snapshot.RefreshedAt.IsZero() {
		snapshot.RefreshedAt = time.Now()
	}
	r.snapshot = snapshot
	r.has = true
	r.stats.LastSuccess = snapshot.RefreshedAt
	r.stats.LastError = ""
	return nil
}

func (r *Refresher) Snapshot() (Snapshot, bool) {
	r.mu.RLock()
	defer r.mu.RUnlock()
	return r.snapshot, r.has
}

func (r *Refresher) Stats() RefreshStats {
	r.mu.RLock()
	defer r.mu.RUnlock()
	return r.stats
}
