package payments

import (
	"context"
	"fmt"
	"time"

	"github.com/gofrs/uuid/v5"
	"github.com/saveinmed/backend-go/internal/domain"
)

// MockGateway provides a fictional payment gateway for testing and development.
// All payments are automatically approved after a short delay.
type MockGateway struct {
	MarketplaceCommission float64
	AutoApprove           bool // If true, payments are auto-approved
}

func NewMockGateway(commission float64, autoApprove bool) *MockGateway {
	return &MockGateway{
		MarketplaceCommission: commission,
		AutoApprove:           autoApprove,
	}
}

func (g *MockGateway) CreatePreference(ctx context.Context, order *domain.Order, payer *domain.User, sellerAcc *domain.SellerPaymentAccount) (*domain.PaymentPreference, error) {
	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	default:
	}

	fee := int64(float64(order.TotalCents) * (g.MarketplaceCommission / 100))

	// Generate a mock payment ID
	mockPaymentID := uuid.Must(uuid.NewV7())

	status := "pending"
	if g.AutoApprove {
		status = "approved"
	}

	pref := &domain.PaymentPreference{
		OrderID:          order.ID,
		Gateway:          "mock",
		CommissionPct:    g.MarketplaceCommission,
		MarketplaceFee:   fee,
		SellerReceivable: order.TotalCents - fee,
		PaymentURL:       fmt.Sprintf("/mock-payment/%s?status=%s", mockPaymentID.String(), status),
	}

	// Simulate minimal latency
	time.Sleep(5 * time.Millisecond)
	return pref, nil
}

// ConfirmPayment simulates payment confirmation for the mock gateway.
func (g *MockGateway) ConfirmPayment(ctx context.Context, paymentID string) (*domain.PaymentResult, error) {
	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	default:
	}

	// Always approve in mock mode
	return &domain.PaymentResult{
		PaymentID:   paymentID,
		Status:      "approved",
		Gateway:     "mock",
		Message:     "Pagamento fictício aprovado automaticamente",
		ConfirmedAt: time.Now(),
	}, nil
}

// RefundPayment simulates a refund for the mock gateway.
func (g *MockGateway) RefundPayment(ctx context.Context, paymentID string, amountCents int64) (*domain.RefundResult, error) {
	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	default:
	}

	return &domain.RefundResult{
		RefundID:    uuid.Must(uuid.NewV7()).String(),
		PaymentID:   paymentID,
		AmountCents: amountCents,
		Status:      "refunded",
		RefundedAt:  time.Now(),
	}, nil
}
