package plan

import (
	"github.com/tech/sendico/pkg/discovery"
	"time"

	"github.com/tech/sendico/payments/storage/model"
	"github.com/tech/sendico/pkg/merrors"
	paymenttypes "github.com/tech/sendico/pkg/payments/types"
	sharedv1 "github.com/tech/sendico/pkg/proto/payments/shared/v1"
)

func buildFXConversionPlan(payment *model.Payment) (*model.PaymentPlan, error) {
	if payment == nil {
		return nil, merrors.InvalidArgument("plan builder: payment is required")
	}
	step := &model.PaymentStep{
		StepID:           "fx_convert",
		Rail:             discovery.RailLedger,
		Action:           discovery.RailOperationFXConvert,
		ReportVisibility: model.ReportVisibilityUser,
		CommitPolicy:     model.CommitPolicyImmediate,
		Amount:           cloneMoney(payment.Intent.Amount),
	}
	return &model.PaymentPlan{
		ID:             payment.PaymentRef,
		Steps:          []*model.PaymentStep{step},
		IdempotencyKey: payment.IdempotencyKey,
		CreatedAt:      planTimestamp(payment),
	}, nil
}

func resolveSettlementAmount(payment *model.Payment, quote *sharedv1.PaymentQuote, fallback *paymenttypes.Money) *paymenttypes.Money {
	if quote != nil && quote.GetExpectedSettlementAmount() != nil {
		return moneyFromProto(quote.GetExpectedSettlementAmount())
	}
	if payment != nil && payment.LastQuote != nil && payment.LastQuote.ExpectedSettlementAmount != nil {
		return cloneMoney(payment.LastQuote.ExpectedSettlementAmount)
	}
	return cloneMoney(fallback)
}

func resolveDebitAmount(payment *model.Payment, quote *sharedv1.PaymentQuote, fallback *paymenttypes.Money) *paymenttypes.Money {
	if quote != nil && quote.GetDebitAmount() != nil {
		return moneyFromProto(quote.GetDebitAmount())
	}
	if payment != nil && payment.LastQuote != nil && payment.LastQuote.DebitAmount != nil {
		return cloneMoney(payment.LastQuote.DebitAmount)
	}
	return cloneMoney(fallback)
}

func resolveFeeAmount(payment *model.Payment, quote *sharedv1.PaymentQuote) *paymenttypes.Money {
	if quote != nil && quote.GetExpectedFeeTotal() != nil {
		return moneyFromProto(quote.GetExpectedFeeTotal())
	}
	if payment != nil && payment.LastQuote != nil {
		return cloneMoney(payment.LastQuote.ExpectedFeeTotal)
	}
	return nil
}

func isPositiveMoney(amount *paymenttypes.Money) bool {
	if amount == nil {
		return false
	}
	val, err := decimalFromMoney(amount)
	if err != nil {
		return false
	}
	return val.IsPositive()
}

func planTimestamp(payment *model.Payment) time.Time {
	if payment != nil && !payment.CreatedAt.IsZero() {
		return payment.CreatedAt.UTC()
	}
	return time.Now().UTC()
}
