package usecase

import (
	"context"
	"fmt"

	"backend/pkg/member/domain"
	"backend/pkg/member/domain/member"
	"backend/pkg/member/domain/usecase"

	"backend/pkg/library/errs"
	"backend/pkg/library/errs/code"
)

func (use *MemberUseCase) GenerateRefreshCode(ctx context.Context, param usecase.GenerateRefreshCodeRequest) (usecase.GenerateRefreshCodeResponse, error) {
	checkType, status := member.GetCodeNameByCode(param.CodeType)
	if !status {
		e := errs.ResourceNotFoundWithScope(
			code.CloudEPMember,
			domain.FailedToGetVerifyCodeErrorCode,
			fmt.Sprintf("failed to get verify code type: %d", param.CodeType),
		)

		return usecase.GenerateRefreshCodeResponse{}, e
	}

	vc, err := use.VerifyCodeModel.IsVerifyCodeExist(ctx, param.LoginID, checkType)
	if err != nil {
		return usecase.GenerateRefreshCodeResponse{}, err
	}
	// 找不到，故要產生
	if vc == "" {
		vc, err = generateVerifyCode(6)
		if err != nil {
			return usecase.GenerateRefreshCodeResponse{}, errs.SystemInternalError(err.Error())
		}

		err = use.VerifyCodeModel.SetVerifyCode(ctx, param.LoginID, checkType, vc)
		if err != nil {
			return usecase.GenerateRefreshCodeResponse{},
				errs.DatabaseErrorWithScope(
					code.CloudEPMember,
					domain.FailedToGetCodeOnRedisErrorCode,
					"failed to set verify code",
				)
		}
	}

	return usecase.GenerateRefreshCodeResponse{
		Data: usecase.VerifyCode{
			VerifyCode: vc,
		},
	}, nil
}

func (use *MemberUseCase) VerifyRefreshCode(ctx context.Context, param usecase.VerifyRefreshCodeRequest) error {
	err := use.CheckRefreshCode(ctx, param)
	if err != nil {
		return err
	}

	//  因為 CheckRefreshCde 中也有驗證一次，這次就讓他不報錯直接過，因為如果有錯誤，上面那個就會報錯了
	checkType, _ := member.GetCodeNameByCode(param.CodeType)
	// todo: 刪不掉看要用什麼方法補刪除，而不是報錯
	_ = use.VerifyCodeModel.DelVerifyCode(ctx, param.LoginID, checkType)

	return nil
}

func (use *MemberUseCase) CheckRefreshCode(ctx context.Context, param usecase.VerifyRefreshCodeRequest) error {
	checkType, status := member.GetCodeNameByCode(param.CodeType)
	if !status {
		return errs.ResourceNotFoundWithScope(
			code.CloudEPMember,
			domain.FailedToGetVerifyCodeErrorCode,
			fmt.Sprintf("failed to get verify code type: %d", param.CodeType),
		)
	}

	get, err := use.VerifyCodeModel.IsVerifyCodeExist(ctx, param.LoginID, checkType)
	if err != nil {
		return errs.DatabaseErrorWithScope(
			code.CloudEPMember,
			domain.FailedToGetCodeOnRedisErrorCode,
			"failed to set verify code",
		)
	}
	if get == "" {
		return errs.ResourceNotFoundWithScope(
			code.CloudEPMember,
			domain.FailedToGetCodeOnRedisErrorCode,
			"failed to get data",
		)
	}

	if get != param.VerifyCode {
		return errs.ForbiddenWithScope(
			code.CloudEPMember,
			domain.FailedToGetCodeCorrectErrorCode,
			"failed to verify code",
		)
	}

	return nil
}

func (use *MemberUseCase) VerifyPlatformAuthResult(ctx context.Context, param usecase.VerifyAuthResultRequest) (usecase.VerifyAuthResultResponse, error) {
	account, err := use.Account.FindOneByAccount(ctx, param.Account)
	if err != nil {
		return usecase.VerifyAuthResultResponse{}, errs.ResourceNotFoundWithScope(
			code.CloudEPMember,
			domain.FailedToFindAccountErrorCode,
			fmt.Sprintf("failed to find account: %s", param.Account),
		)
	}

	return usecase.VerifyAuthResultResponse{
		Status: CheckPasswordHash(param.Token, account.Token),
	}, nil
}
