package gateway

import (
	"strings"
	"time"

	"github.com/tech/sendico/gateway/aurora/storage/model"
	clockpkg "github.com/tech/sendico/pkg/clock"
	mntxv1 "github.com/tech/sendico/pkg/proto/gateway/mntx/v1"
	"google.golang.org/protobuf/types/known/timestamppb"
)

func tsOrNow(clock clockpkg.Clock, ts *timestamppb.Timestamp) time.Time {
	if ts == nil {
		return clock.Now()
	}
	return ts.AsTime()
}

func CardPayoutStateFromProto(clock clockpkg.Clock, p *mntxv1.CardPayoutState) *model.CardPayout {
	if p == nil {
		return nil
	}

	return &model.CardPayout{
		PaymentRef:        strings.TrimSpace(p.GetParentPaymentRef()),
		OperationRef:      p.GetOperationRef(),
		IntentRef:         p.GetIntentRef(),
		Comment:           strings.TrimSpace(p.GetComment()),
		IdempotencyKey:    p.GetIdempotencyKey(),
		ProjectID:         p.ProjectId,
		CustomerID:        p.CustomerId,
		AmountMinor:       p.AmountMinor,
		Currency:          p.Currency,
		Status:            payoutStatusFromProto(p.Status),
		ProviderCode:      p.ProviderCode,
		ProviderMessage:   p.ProviderMessage,
		ProviderPaymentID: p.ProviderPaymentId,
		CreatedAt:         tsOrNow(clock, p.CreatedAt),
		UpdatedAt:         tsOrNow(clock, p.UpdatedAt),
	}
}

func StateToProto(m *model.CardPayout) *mntxv1.CardPayoutState {
	return &mntxv1.CardPayoutState{
		PayoutId:          firstNonEmpty(m.OperationRef, m.PaymentRef),
		ParentPaymentRef:  m.PaymentRef,
		ProjectId:         m.ProjectID,
		CustomerId:        m.CustomerID,
		AmountMinor:       m.AmountMinor,
		Currency:          m.Currency,
		Status:            payoutStatusToProto(m.Status),
		ProviderCode:      m.ProviderCode,
		ProviderMessage:   m.ProviderMessage,
		ProviderPaymentId: m.ProviderPaymentID,
		Comment:           strings.TrimSpace(m.Comment),
		CreatedAt:         timestamppb.New(m.CreatedAt),
		UpdatedAt:         timestamppb.New(m.UpdatedAt),
	}
}

func payoutStatusToProto(s model.PayoutStatus) mntxv1.PayoutStatus {
	switch s {
	case model.PayoutStatusCreated:
		return mntxv1.PayoutStatus_PAYOUT_STATUS_CREATED
	case model.PayoutStatusProcessing:
		return mntxv1.PayoutStatus_PAYOUT_STATUS_WAITING
	case model.PayoutStatusWaiting:
		return mntxv1.PayoutStatus_PAYOUT_STATUS_WAITING
	case model.PayoutStatusSuccess:
		return mntxv1.PayoutStatus_PAYOUT_STATUS_SUCCESS
	case model.PayoutStatusFailed:
		return mntxv1.PayoutStatus_PAYOUT_STATUS_FAILED
	case model.PayoutStatusCancelled:
		return mntxv1.PayoutStatus_PAYOUT_STATUS_CANCELLED
	default:
		return mntxv1.PayoutStatus_PAYOUT_STATUS_CREATED
	}
}

func payoutStatusFromProto(s mntxv1.PayoutStatus) model.PayoutStatus {
	switch s {
	case mntxv1.PayoutStatus_PAYOUT_STATUS_CREATED:
		return model.PayoutStatusCreated

	case mntxv1.PayoutStatus_PAYOUT_STATUS_WAITING:
		return model.PayoutStatusWaiting

	case mntxv1.PayoutStatus_PAYOUT_STATUS_SUCCESS:
		return model.PayoutStatusSuccess

	case mntxv1.PayoutStatus_PAYOUT_STATUS_FAILED:
		return model.PayoutStatusFailed

	case mntxv1.PayoutStatus_PAYOUT_STATUS_CANCELLED:
		return model.PayoutStatusCancelled

	default:
		return model.PayoutStatusCreated
	}
}
