package payments

import (
	"context"
	"log"

	"crussell/db"
)

type VATConfig struct {
	IsVATRegistered bool
	DefaultVATRate  float64
	VoucherType     string
}

// GetVATConfig reads VAT config using the given querier, which can be either
// a *db.PoolProxy (for non-transactional reads), a pgx.Tx (to read inside a
// transaction), or any other type that implements db.Querier.
func GetVATConfig(ctx context.Context, q db.Querier) (*VATConfig, error) {
	var cfg VATConfig
	err := q.QueryRow(ctx, `
		SELECT COALESCE(is_vat_registered, FALSE),
		       COALESCE(default_vat_rate, 20.0),
		       COALESCE(voucher_type, 'SPV')
		FROM business_settings
		LIMIT 1
	`).Scan(&cfg.IsVATRegistered, &cfg.DefaultVATRate, &cfg.VoucherType)
	if err != nil {
		return nil, err
	}
	return &cfg, nil
}

// ApplyVATToBookingPayment reads VAT config and calls apply_vat_to_payment
// on a booking payment record. The q parameter is used for both reading the
// VAT config and for the defensive payment-method check, ensuring all reads
// are consistent with the caller's transactional context. Errors are logged
// — VAT failure should not block the payment flow.
func ApplyVATToBookingPayment(ctx context.Context, q db.Querier, paymentID string) {
	vatCfg, err := GetVATConfig(ctx, q)
	if err != nil {
		log.Printf("Failed to read VAT config for payment %s: %v", paymentID, err)
		return
	}
	if !vatCfg.IsVATRegistered {
		return
	}
	// Discount, on_the_house, and tip payments must never have VAT applied.
	// Read the payment method and type inside the same transactional context
	// so that the just-inserted row is visible (defence against READ
	// COMMITTED isolation when q is a pgx.Tx).
	var method, ptype string
	if qErr := q.QueryRow(ctx, "SELECT payment_method, payment_type FROM payments WHERE id = $1", paymentID).Scan(&method, &ptype); qErr == nil && (method == "discount" || method == "on_the_house" || ptype == "tip") {
		return
	}
	if _, execErr := q.Exec(ctx, "SELECT apply_vat_to_payment($1, $2)", paymentID, vatCfg.DefaultVATRate); execErr != nil {
		log.Printf("Failed to apply VAT to payment %s: %v", paymentID, execErr)
	}
}

// ApplyVATToTillSale reads VAT config and calls apply_vat_to_till_sale for
// SPV gift card till sales. Errors are logged — VAT failure should not
// block the sale flow.
func ApplyVATToTillSale(ctx context.Context, q db.Querier, saleID string) {
	vatCfg, err := GetVATConfig(ctx, q)
	if err != nil {
		log.Printf("Failed to read VAT config for till sale %s: %v", saleID, err)
		return
	}
	if !vatCfg.IsVATRegistered || vatCfg.VoucherType != "SPV" {
		return
	}
	if _, execErr := q.Exec(ctx, "SELECT apply_vat_to_till_sale($1, $2)", saleID, vatCfg.DefaultVATRate); execErr != nil {
		log.Printf("Failed to apply VAT to till sale %s: %v", saleID, execErr)
	}
}


