package testutils

import (
	"context"
	"testing"

	smsprovider "git.gocasts.ir/ebhomengo/niki/adapter/sms_provider/kavenegar"
	kavenegarotp "git.gocasts.ir/ebhomengo/niki/adapter/sms_provider/kavenegar/otp"
	"git.gocasts.ir/ebhomengo/niki/config"
	benefactorkindboxreqhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/benefactor/kind_box_req"
	"git.gocasts.ir/ebhomengo/niki/internal/initial"
	addressparam "git.gocasts.ir/ebhomengo/niki/param/benefactor/address"
	benefactoreparam "git.gocasts.ir/ebhomengo/niki/param/benefactor/benefactore"
	"git.gocasts.ir/ebhomengo/niki/repository/mysql"
	mysqladdress "git.gocasts.ir/ebhomengo/niki/repository/mysql/address"
	mysqlbenefactor "git.gocasts.ir/ebhomengo/niki/repository/mysql/benefactor"
	mysqlkindboxreq "git.gocasts.ir/ebhomengo/niki/repository/mysql/kind_box_req"
	redisotp "git.gocasts.ir/ebhomengo/niki/repository/redis/redis_otp"
	authservice "git.gocasts.ir/ebhomengo/niki/service/auth"
	benefactoraddressservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/address"
	benefactorservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/benefactor"
	benefactorkindboxreqservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box_req"
	benefactorkindboxreqvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/kind_box_req"
	"github.com/brianvoe/gofakeit/v6"
	"github.com/stretchr/testify/assert"
)

var (
	benefactorSvc               benefactorservice.Service
	benefactorAddressSvc        benefactoraddressservice.Service
	BenefactorkindBoxReqHandler benefactorkindboxreqhandler.Handler
	AuthSvc                     authservice.Service
	MysqlRepo                   *mysql.DB
	AuthConfig                  authservice.Config
)

func SetupEnd2EndTest(t *testing.T) {
	t.Helper()
	cfg := config.C()

	MysqlRepo = Setup(t)
	redisAdapter := SetupRedis(t)

	AuthSvc = initial.InitBenefactorAuthService(cfg)

	RedisOtp := redisotp.New(redisAdapter)
	benefactorMysql := mysqlbenefactor.New(MysqlRepo)
	kavenegarSmsProvider := smsprovider.New(cfg.KavenegarSmsProvider)
	otpSmsProvider := kavenegarotp.New(kavenegarSmsProvider)
	benefactorSvc = benefactorservice.New(cfg.BenefactorSvc, RedisOtp, otpSmsProvider, AuthSvc, benefactorMysql)
	benefactorAddressMysql := mysqladdress.New(MysqlRepo)
	benefactorAddressSvc = benefactoraddressservice.New(benefactorAddressMysql)
	benefactorKindBoxReqMysql := mysqlkindboxreq.New(MysqlRepo)
	benefactorKindBoxReqSvc := benefactorkindboxreqservice.New(benefactorKindBoxReqMysql)
	benefactorKindBoxReqVld := benefactorkindboxreqvalidator.New(benefactorSvc, benefactorAddressSvc)

	BenefactorkindBoxReqHandler = benefactorkindboxreqhandler.New(cfg.Auth, AuthSvc, benefactorKindBoxReqSvc, benefactorKindBoxReqVld)

	//nolint
	return
}

func SendOTP(t *testing.T) benefactoreparam.SendOtpResponse {
	t.Helper()
	req := benefactoreparam.SendOtpRequest{PhoneNumber: gofakeit.Phone()}
	ctx := context.Background()
	resp, err := benefactorSvc.SendOtp(ctx, req)
	if err != nil {
		t.Logf(err.Error())
	}

	return resp
}

// nolint
func CreateBenefactorWithSvc(t *testing.T, req benefactoreparam.LoginOrRegisterRequest) (benefactoreparam.LoginOrRegisterResponse, func()) {
	t.Helper()
	ctx := context.Background()
	resp, err := benefactorSvc.LoginOrRegister(ctx, req)
	if err != nil {
		t.Logf(err.Error())
	}

	return resp, func() {
		_, err := MysqlRepo.Conn().ExecContext(ctx, `delete from benefactors where id=?`,
			resp.BenefactorInfo.ID)
		assert.Nil(t, err)
	}
}

// nolint
func CreateAddressWithSvc(t *testing.T, req addressparam.BenefactorAddAddressRequest) (addressparam.BenefactorAddAddressResponse, func()) {
	t.Helper()
	ctx := context.Background()
	resp, err := benefactorAddressSvc.Add(ctx, req)
	if err != nil {
		t.Logf(err.Error())
	}

	return resp, func() {
		_, err := MysqlRepo.Conn().ExecContext(ctx, `delete from addresses where id=?`,
			resp.Address.ID)
		assert.Nil(t, err)
	}
}