package repository

import (
	"context"
	"database/sql"
	"fmt"

	"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
)

type CurrencyRepository interface {
	GetExchangeRate(ctx context.Context, from, to domain.IntCurrency) (domain.IntCurrencyRate, error)
	StoreExchangeRate(ctx context.Context, rate domain.IntCurrencyRate) error
	GetSupportedCurrencies(ctx context.Context) ([]domain.IntCurrency, error)
}

type CurrencyPostgresRepository struct {
	store *Store
}

func NewCurrencyPostgresRepository(store *Store) *CurrencyPostgresRepository {
	return &CurrencyPostgresRepository{store: store}
}

func (r *CurrencyPostgresRepository) GetExchangeRate(ctx context.Context, from, to domain.IntCurrency) (domain.IntCurrencyRate, error) {
	const query = `
		SELECT from_currency, to_currency, rate, precision, valid_until 
		FROM exchange_rates 
		WHERE from_currency = $1 AND to_currency = $2 AND valid_until > NOW()
		ORDER BY created_at DESC
		LIMIT 1`

	var rate domain.IntCurrencyRate
	err := r.store.conn.QueryRow(ctx, query, from, to).Scan(
		&rate.From,
		&rate.To,
		&rate.Rate,
		&rate.ValidUntil,
	)
	if err != nil {
		if err == sql.ErrNoRows {
			return domain.IntCurrencyRate{}, fmt.Errorf("%w: no rate found for %s to %s",
				domain.ErrIntCurrencyConversion, from, to)
		}
		return domain.IntCurrencyRate{}, fmt.Errorf("failed to get exchange rate: %w", err)
	}

	return rate, nil
}

func (r *CurrencyPostgresRepository) StoreExchangeRate(ctx context.Context, rate domain.IntCurrencyRate) error {
	const query = `
		INSERT INTO exchange_rates (from_currency, to_currency, rate, precision, valid_until)
		VALUES ($1, $2, $3, $4, $5)
		ON CONFLICT (from_currency, to_currency) 
		DO UPDATE SET 
			rate = EXCLUDED.rate,
			precision = EXCLUDED.precision,
			valid_until = EXCLUDED.valid_until,
			created_at = NOW()`

	_, err := r.store.conn.Exec(ctx, query,
		rate.From,
		rate.To,
		rate.Rate,
		rate.ValidUntil)
	if err != nil {
		return fmt.Errorf("failed to store exchange rate: %w", err)
	}

	return nil
}

func (r *CurrencyPostgresRepository) GetSupportedCurrencies(ctx context.Context) ([]domain.IntCurrency, error) {
	const query = `SELECT DISTINCT currency FROM supported_currencies ORDER BY currency`

	var currencies []domain.IntCurrency
	rows, err := r.store.conn.Query(ctx, query)
	if err != nil {
		return nil, fmt.Errorf("failed to get supported currencies: %w", err)
	}
	defer rows.Close()

	for rows.Next() {
		var currency domain.IntCurrency
		if err := rows.Scan(&currency); err != nil {
			return nil, fmt.Errorf("failed to scan currency: %w", err)
		}
		currencies = append(currencies, currency)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("row iteration error: %w", err)
	}

	return currencies, nil
}
