package user

import (
	"context"
	"database/sql"
	"os"
	"time"

	"in-server/app/main/api/internal/svc"
	"in-server/app/main/api/internal/types"
	"in-server/app/main/model"
	"in-server/common/xerr"
	"in-server/pkg/lzkit/crypto"

	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/logx"
)

// PasswordLoginLogic 账号密码登录（使用手机号作为账号）
type PasswordLoginLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewPasswordLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PasswordLoginLogic {
	return &PasswordLoginLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *PasswordLoginLogic) PasswordLogin(req *types.PasswordLoginReq) (resp *types.PasswordLoginResp, err error) {
	// 加密手机号以匹配数据库中的存储格式
	secretKey := l.svcCtx.Config.Encrypt.SecretKey
	encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "密码登录, 加密手机号失败: %+v", err)
	}

	// 查找用户
	user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
	if findUserErr != nil && !errors.Is(findUserErr, model.ErrNotFound) {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "密码登录, 查询用户失败, mobile: %s, err: %+v", encryptedMobile, findUserErr)
	}
	if user == nil {
		return nil, errors.Wrapf(xerr.NewErrMsg("账号或密码错误"), "密码登录, 用户不存在: %s", encryptedMobile)
	}

	// 校验密码（开发环境允许空密码快速登录，便于调试）
	if os.Getenv("ENV") == "development" && req.Password == "" {
		logx.Infof("密码登录开发模式下允许空密码, userId=%s", user.Id)
	} else {
		if !user.Password.Valid || user.Password.String == "" {
			return nil, errors.Wrapf(xerr.NewErrMsg("账号未设置密码，请联系管理员"), "密码登录, 用户未设置密码: %s", encryptedMobile)
		}
		if !crypto.PasswordVerify(req.Password, user.Password.String) {
			return nil, errors.Wrapf(xerr.NewErrMsg("账号或密码错误"), "密码登录, 密码不匹配: %s", encryptedMobile)
		}
	}

	// 生成访问 Token
	token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, user.Id)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "密码登录, 生成token失败 : %s", user.Id)
	}

	now := time.Now().Unix()
	return &types.PasswordLoginResp{
		AccessToken:  token,
		AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
		RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
	}, nil
}

