package callback

import (
	"context"
	"log"
	"fmt"

	"go.uber.org/zap"
	"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
	"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
	tb "gopkg.in/tucnak/telebot.v2"
)

type accountRepository interface {
	FindByUserID(context.Context, string) (*models.Account, errors.Error)
}

type historyService interface {
	CreateHistory(ctx context.Context, history *models.History) (*models.History, errors.Error)
}

type walletService interface {
	ReplenishAccountWallet(context.Context, *models.ReplenishAccountWallet) (*models.Account, errors.Error)
}

type PaymentCallbackServiceDeps struct {
	Logger            *zap.Logger
	AccountRepository accountRepository
	WalletService     walletService
	HistoryService    historyService
	Notifier					*tb.Bot
	NotifyChannel			int64
	AdminURL 					string
}

type PaymentCallbackService struct {
	logger            *zap.Logger
	accountRepository accountRepository
	walletService     walletService
	historyService    historyService
	notifier					*tb.Bot
	notifyChannel 		int64
	adminURL 					string
}

func NewPaymentCallbackService(deps PaymentCallbackServiceDeps) *PaymentCallbackService {
	if deps.Logger == nil {
		log.Panicln("logger is nil on <New (payment callback service)>")
	}

	if deps.AccountRepository == nil {
		log.Panicln("AccountRepository is nil on <New (payment callback service)>")
	}

	if deps.WalletService == nil {
		log.Panicln("WalletService is nil on <New (payment callback service)>")
	}

	if deps.HistoryService == nil {
		log.Panicln("HistoryService is nil on <New (payment callback service)>")
	}

	return &PaymentCallbackService{
		logger:            deps.Logger,
		accountRepository: deps.AccountRepository,
		walletService:     deps.WalletService,
		historyService:    deps.HistoryService,
		notifier:					 deps.Notifier,
		notifyChannel:					 deps.NotifyChannel,
		adminURL:					 deps.AdminURL,
	}
}

func (receiver *PaymentCallbackService) SuccessEvent(ctx context.Context, event *models.PaymentEvent) errors.Error {
	account, err := receiver.accountRepository.FindByUserID(ctx, event.UserID)
	if err != nil {
		receiver.logger.Error("failed to get account on <SuccessEvent> of <PaymentCallbackService>", zap.Error(err))
		return err
	}

	if account.Wallet.LastPaymentID == event.PaymentID {
		receiver.logger.Info("payment already was executed on <SuccessEvent> of <PaymentCallbackService>", zap.String("paymentID", event.PaymentID))
		return nil
	}

	if _, err := receiver.walletService.ReplenishAccountWallet(ctx, &models.ReplenishAccountWallet{
		Cash:      event.Amount,
		Currency:  event.Currency,
		PaymentID: event.PaymentID,
		Account:   account,
	}); err != nil {
		receiver.logger.Error("failed to replenish wallet on <SuccessEvent> of <PaymentCallbackService>", zap.Error(err))
		return err
	}

	//go func() {
	if _, err := receiver.historyService.CreateHistory(ctx, &models.History{
		UserID:  account.UserID,
		Comment: event.Message,
		Key:     event.Key,
		RawDetails: models.RawDetails{
			Price:   event.Amount,
			Comment: event.Type + ":" + event.Currency,
		},
	}); err != nil {
		receiver.logger.Error("failed to create history on <SuccessEvent> of <PaymentCallbackService>", zap.Error(err))
		return err
	}
	//}()
go func () {
	if _, err := receiver.notifier.Send(tb.ChatID(receiver.notifyChannel), fmt.Sprintf(`Внесены деньги %.2f, пользователем %s`,float64(event.Amount/100), receiver.adminURL + "/users/" + account.UserID)); err != nil {
		fmt.Println("TBOER", err)
	}
}()
	return nil
}

func (receiver *PaymentCallbackService) FailureEvent(ctx context.Context, event *models.PaymentEvent) errors.Error {
	if _, err := receiver.historyService.CreateHistory(ctx, &models.History{
		UserID:  event.UserID,
		Comment: event.Message,
		Key:     event.Key,
		//	RawDetails: fmt.Sprintf("%d%s", event.Amount, event.Currency),
	}); err != nil {
		receiver.logger.Error("failed to create history on <FailureEvent> of <PaymentCallbackService>", zap.Error(err))
		return err
	}

	return nil
}
