package service

import (
	"github.com/linmadan/egglib-go/core/application"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/auth/command"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/auth/dto"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/auth/query"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/factory"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
	"strconv"
	"time"
)

// 认证服务
type AuthService struct {
}

// 企业注册
func (authService *AuthService) CompanySignUp(companySignUpCommand *command.CompanySignUpCommand) (interface{}, error) {
	if err := companySignUpCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	//var user *domain.User
	signUpCompanyService, err := factory.CreateSignUpCompanyService(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	companyInfo := &domain.CompanyInfo{
		CompanyName:      companySignUpCommand.CompanyName,
		Scale:            companySignUpCommand.Scale,
		Logo:             "",
		Address:          "",
		IndustryCategory: companySignUpCommand.IndustryCategory,
		RegisteredTime:   time.Now(),
	}
	userInfo := &domain.UserInfo{
		UserName: companySignUpCommand.Contacts,
		Phone:    companySignUpCommand.Phone,
	}
	if _, err = signUpCompanyService.SignUpCompany(companySignUpCommand.Phone, companySignUpCommand.Password, companyInfo, userInfo); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return struct{}{}, nil
}

// 个人注册
func (authService *AuthService) UserSignUp(companySignUpCommand *command.UserSignUpCommand) (interface{}, error) {
	if err := companySignUpCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	signUpPersonService, err := factory.CreatePgSignUpPersonService(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	userInfo := &domain.UserInfo{
		UserName: companySignUpCommand.Name,
		Phone:    companySignUpCommand.Phone,
		Referer:  companySignUpCommand.Referrer,
	}
	if _, err = signUpPersonService.SignUp(companySignUpCommand.Phone, companySignUpCommand.Password, userInfo); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return struct{}{}, nil
}

// 注销账号 (添加用户时重新激活)
func (authService *AuthService) DestroyAccount(destroyAccountCommand *command.DestroyAccountCommand) (interface{}, error) {
	if err := destroyAccountCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	accountDestroyService, err := factory.CreatePgAuthAccountDestroyService(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := accountDestroyService.DestroyAccount(nil, destroyAccountCommand.Account); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}

	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return struct{}{}, nil
}

// 修改密码
func (authService *AuthService) PhoneAuthChangePassword(phoneAuthChangePasswordCommand *command.PhoneAuthChangePasswordCommand) (interface{}, error) {
	if err := phoneAuthChangePasswordCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	var userRepository domain.UserRepository
	if value, err := factory.CreateUserRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	} else {
		userRepository = value
	}
	var userBaseId int64
	if user, err := userRepository.FindOne(map[string]interface{}{"userId": phoneAuthChangePasswordCommand.UserId}); err != nil {
		if err == domain.ErrorNotFound {
			return nil, application.ThrowError(application.TRANSACTION_ERROR, "该用户不存在")
		}
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	} else {
		userBaseId = user.UserBaseId
	}

	var userBaseRepository domain.UserBaseRepository
	if value, err := factory.CreateUserBaseRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	} else {
		userBaseRepository = value
	}
	userBase, err := userBaseRepository.FindOne(map[string]interface{}{"userBaseId": userBaseId})
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err == domain.ErrorNotFound {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, "该用户不存在")
	}
	if err := userBase.CheckAccountPassword(userBase.Account, phoneAuthChangePasswordCommand.OldPassword); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := userBase.ResetPassword(userBase.Account, phoneAuthChangePasswordCommand.NewPassword); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if _, err = userBaseRepository.Save(userBase); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}

	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return struct {
	}{}, nil
}

// 手机账号密码检查
func (authService *AuthService) PhoneAuthCheck(phoneAuthCheckCommand *command.PhoneAuthCheckCommand) (interface{}, error) {
	if err := phoneAuthCheckCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	var userBaseRepository domain.UserBaseRepository
	if value, err := factory.CreateUserBaseRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	} else {
		userBaseRepository = value
	}
	userBase, err := userBaseRepository.FindOne(map[string]interface{}{"account": phoneAuthCheckCommand.Phone})
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err == domain.ErrorNotFound {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, "该用户不存在")
	}
	if err := userBase.CheckAccountPassword(phoneAuthCheckCommand.Phone, phoneAuthCheckCommand.Password); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}

	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return userBase, nil
}

// 重置密码(忘记密码)
func (authService *AuthService) PhoneAuthResetPassword(phoneAuthResetPasswordCommand *command.PhoneAuthResetPasswordCommand) (interface{}, error) {
	if err := phoneAuthResetPasswordCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	var userBaseRepository domain.UserBaseRepository
	if value, err := factory.CreateUserBaseRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	} else {
		userBaseRepository = value
	}
	userBase, err := userBaseRepository.FindOne(map[string]interface{}{"account": phoneAuthResetPasswordCommand.Phone})
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err == domain.ErrorNotFound {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, "该用户不存在")
	}
	if err := userBase.ResetPassword(phoneAuthResetPasswordCommand.Phone, phoneAuthResetPasswordCommand.Password); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}

	if _, err = userBaseRepository.Save(userBase); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}

	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return struct{}{}, nil
}

// 重置手机号
func (authService *AuthService) PhoneAuthResetPhone(phoneAuthResetPhoneCommand *command.PhoneAuthResetPhoneCommand) (interface{}, error) {
	if err := phoneAuthResetPhoneCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	resetPhoneService, err := factory.CreatePgAuthResetPhoneService(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := resetPhoneService.ResetPhone(nil, phoneAuthResetPhoneCommand.OldPhone, phoneAuthResetPhoneCommand.NewPhone); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return struct{}{}, nil
}

// 刷新IM信息
func (authService *AuthService) RefreshIM(refreshIMCommand *command.RefreshIMCommand) (interface{}, error) {
	if err := refreshIMCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	imService, _ := factory.CreatePgImService(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	userId, _ := strconv.Atoi(refreshIMCommand.Phone)
	imInfo, err := imService.InitOrUpdateUserIMInfo(int64(userId), refreshIMCommand.RefreshFlag)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return imInfo, nil
}

// 用户信息
func (authService *AuthService) UserInfo(userInfoQuery *query.UserInfoQuery) (interface{}, error) {
	if err := userInfoQuery.ValidateQuery(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	var userBase *domain.UserBase
	userBaseRepository, _, _ := factory.FastPgUserBase(transactionContext, 0)
	if len(userInfoQuery.Account) > 0 {
		userBase, err = userBaseRepository.FindOne(map[string]interface{}{"account": userInfoQuery.Account})
	} else if userInfoQuery.UserBaseId > 0 {
		userBase, err = userBaseRepository.FindOne(map[string]interface{}{"userBaseId": userInfoQuery.UserBaseId})
	}
	if err != nil {
		return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
	}
	ubDto := &dto.UserBaseDto{}
	ubDto.LoadDto(userBase)
	userRepository, _, _ := factory.FastPgUser(transactionContext, 0)
	if user, err := userRepository.FindOne(map[string]interface{}{"userBaseId": userBase.UserBaseId, "userType": domain.UserTypeVisitor}); err == nil {
		ubDto.UserId = user.UserId
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return ubDto, nil
}

func NewAuthService(options map[string]interface{}) *AuthService {
	newAuthService := &AuthService{}
	return newAuthService
}