package fee

import (
	"context"
	"fmt"
	"math/big"

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

// Oracle provides gas price estimates
type Oracle struct {
	db      *pgxpool.Pool
	chainID int
}

// NewOracle creates a new fee oracle
func NewOracle(db *pgxpool.Pool, chainID int) *Oracle {
	return &Oracle{
		db:      db,
		chainID: chainID,
	}
}

// FeeEstimate represents gas price estimates
type FeeEstimate struct {
	Slow     string `json:"slow"`
	Standard string `json:"standard"`
	Fast     string `json:"fast"`
	Urgent   string `json:"urgent"`
}

// GetFeeEstimates gets current fee estimates
func (o *Oracle) GetFeeEstimates(ctx context.Context) (*FeeEstimate, error) {
	// Get recent gas prices from last 100 blocks
	query := `
		SELECT avg_gas_price
		FROM gas_price_history
		WHERE chain_id = $1
		ORDER BY time DESC
		LIMIT 100
	`

	rows, err := o.db.Query(ctx, query, o.chainID)
	if err != nil {
		return nil, fmt.Errorf("failed to query gas prices: %w", err)
	}
	defer rows.Close()

	var prices []int64
	for rows.Next() {
		var price int64
		if err := rows.Scan(&price); err == nil {
			prices = append(prices, price)
		}
	}

	if len(prices) == 0 {
		// Return default estimates if no data
		return &FeeEstimate{
			Slow:     "20000000000",
			Standard: "30000000000",
			Fast:     "50000000000",
			Urgent:   "100000000000",
		}, nil
	}

	// Calculate percentiles
	p25 := percentile(prices, 0.25)
	p50 := percentile(prices, 0.50)
	p75 := percentile(prices, 0.75)
	p95 := percentile(prices, 0.95)

	return &FeeEstimate{
		Slow:     big.NewInt(p25).String(),
		Standard: big.NewInt(p50).String(),
		Fast:     big.NewInt(p75).String(),
		Urgent:   big.NewInt(p95).String(),
	}, nil
}

// percentile calculates percentile of sorted slice
func percentile(data []int64, p float64) int64 {
	if len(data) == 0 {
		return 0
	}

	index := int(float64(len(data)) * p)
	if index >= len(data) {
		index = len(data) - 1
	}

	return data[index]
}

