package usecase

import (
	errs "backend/pkg/library/errors"
	"context"
	"fmt"

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

func (use *MemberUseCase) GenerateRefreshCode(ctx context.Context, param usecase.GenerateRefreshCodeRequest) (usecase.GenerateRefreshCodeResponse, error) {
	checkType, status := member.GetCodeNameByCode(param.CodeType)
	if !status {
		e := errs.ResNotFoundError(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.SysInternalError(err.Error())
		}

		err = use.VerifyCodeModel.SetVerifyCode(ctx, param.LoginID, checkType, vc)
		if err != nil {
			return usecase.GenerateRefreshCodeResponse{},
				errs.DBErrorError("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.ResNotFoundError(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.DBErrorErrorL(
			use.Logger,
			[]errs.LogField{
				{Key: "err", Val: err.Error()},
			},
			"failed to set verify code",
		)
	}
	if get == "" {
		return errs.ResNotFoundError("failed to get data", param.LoginID, checkType)
	}

	if get != param.VerifyCode {
		return errs.AuthForbiddenError("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.ResNotFoundError(fmt.Sprintf("failed to find account: %s", param.Account))
	}

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