package service

import (
	"context"
	"tydata-server/app/main/api/internal/config"
	"tydata-server/app/main/model"
	"tydata-server/common/ctxdata"
	jwtx "tydata-server/common/jwt"
	"tydata-server/common/xerr"
	"database/sql"

	"github.com/google/uuid"
	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

type UserService struct {
	Config        *config.Config
	userModel     model.UserModel
	userAuthModel model.UserAuthModel
	userTempModel model.UserTempModel
	agentModel    model.AgentModel
}

// NewUserService 创建UserService实例
func NewUserService(config *config.Config, userModel model.UserModel, userAuthModel model.UserAuthModel, userTempModel model.UserTempModel, agentModel model.AgentModel) *UserService {
	return &UserService{
		Config:        config,
		userModel:     userModel,
		userAuthModel: userAuthModel,
		userTempModel: userTempModel,
		agentModel:    agentModel,
	}
}

// GenerateUUIDUserId 生成UUID用户ID
func (s *UserService) GenerateUUIDUserId(ctx context.Context) (string, error) {
	id := uuid.NewString()
	return id, nil
}

// RegisterUUIDUser 注册UUID用户，返回用户ID
func (s *UserService) RegisterUUIDUser(ctx context.Context) (int64, error) {
	// 生成UUID
	uuidStr, err := s.GenerateUUIDUserId(ctx)
	if err != nil {
		return 0, err
	}

	var userId int64
	err = s.userModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error {
		// 创建用户记录
		user := &model.User{}
		result, err := s.userModel.Insert(ctx, session, user)
		if err != nil {
			return err
		}
		userId, err = result.LastInsertId()
		if err != nil {
			return err
		}

		// 创建用户认证记录
		userAuth := &model.UserAuth{
			UserId:   userId,
			AuthType: model.UserAuthTypeUUID,
			AuthKey:  uuidStr,
		}
		_, err = s.userAuthModel.Insert(ctx, session, userAuth)
		return err
	})
	if err != nil {
		return 0, err
	}

	return userId, nil
}

// generalUserToken 生成用户token
func (s *UserService) GeneralUserToken(ctx context.Context, userID int64, userType int64) (string, error) {
	platform, err := ctxdata.GetPlatformFromCtx(ctx)
	if err != nil {
		return "", err
	}

	var isAgent int64
	var agentID int64
	if userType == model.UserTypeNormal {
		agent, err := s.agentModel.FindOneByUserId(ctx, userID)
		if err != nil && !errors.Is(err, model.ErrNotFound) {
			return "", err
		}
		if agent != nil {
			agentID = agent.Id
			isAgent = model.AgentStatusYes
		}
	} else {
		userTemp, err := s.userTempModel.FindOne(ctx, userID)
		if err != nil {
			return "", err
		}
		if userTemp != nil {
			userID = userTemp.Id
		}
	}
	token, generaErr := jwtx.GenerateJwtToken(jwtx.JwtClaims{
		UserId:   userID,
		AgentId:  agentID,
		Platform: platform,
		UserType: userType,
		IsAgent:  isAgent,
	}, s.Config.JwtAuth.AccessSecret, s.Config.JwtAuth.AccessExpire)
	if generaErr != nil {
		return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "更新token, 生成token失败 : %d", userID)
	}
	return token, nil
}

// RegisterUser 注册用户，返回用户ID
// 传入手机号，自动注册，如果ctx存在临时用户则临时用户转为正式用户
func (s *UserService) RegisterUser(ctx context.Context, mobile string) (int64, error) {
	claims, err := ctxdata.GetClaimsFromCtx(ctx)
	if err != nil && !errors.Is(err, ctxdata.ErrNoInCtx) {
		return 0, err
	}
	user, err := s.userModel.FindOneByMobile(ctx, sql.NullString{String: mobile, Valid: true})
	if err != nil && !errors.Is(err, model.ErrNotFound) {
		return 0, err
	}
	if user != nil {
		return 0, errors.New("用户已注册")
	}
	// 普通注册
	if claims == nil {
		var userId int64
		err = s.userModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error {
			user := &model.User{
				Mobile: sql.NullString{String: mobile, Valid: true},
			}
			result, err := s.userModel.Insert(ctx, session, user)
			if err != nil {
				return err
			}
			userId, err = result.LastInsertId()
			if err != nil {
				return err
			}
			s.userAuthModel.Insert(ctx, session, &model.UserAuth{
				UserId:   userId,
				AuthType: model.UserAuthTypeMobile,
				AuthKey:  mobile,
			})
			return nil
		})
		if err != nil {
			return 0, err
		}
		return userId, nil
	}

	// 双重判断是否已经注册
	if claims.UserType == model.UserTypeNormal {
		return 0, errors.New("用户已注册")
	}
	var userId int64
	// 临时转正式注册
	err = s.userModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error {
		user := &model.User{
			Mobile: sql.NullString{String: mobile, Valid: true},
		}
		result, err := s.userModel.Insert(ctx, session, user)
		if err != nil {
			return err
		}
		userId, err = result.LastInsertId()
		if err != nil {
			return err
		}
		_, err = s.userAuthModel.Insert(ctx, session, &model.UserAuth{
			UserId:   userId,
			AuthType: model.UserAuthTypeMobile,
			AuthKey:  mobile,
		})
		if err != nil {
			return err
		}
		err = s.TempUserBindUser(ctx, session, userId)
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return 0, err
	}
	return userId, nil
}

// TempUserBindUser 临时用户绑定用户
func (s *UserService) TempUserBindUser(ctx context.Context, session sqlx.Session, normalUserID int64) error {
	claims, err := ctxdata.GetClaimsFromCtx(ctx)
	if err != nil && !errors.Is(err, ctxdata.ErrNoInCtx) {
		return err
	}

	if claims == nil || claims.UserType != model.UserTypeTemp {
		return errors.New("无临时用户")
	}

	// 使用事务上下文查询临时用户
	userTemp, err := s.userTempModel.FindOne(ctx, claims.UserId)
	if err != nil {
		return err
	}

	// 检查是否已经注册过
	userAuth, err := s.userAuthModel.FindOneByAuthTypeAuthKey(ctx, userTemp.AuthType, userTemp.AuthKey)
	if err != nil && !errors.Is(err, model.ErrNotFound) {
		return err
	}
	if userAuth != nil {
		return errors.New("临时用户已注册")
	}

	if session == nil {
		err := s.userAuthModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error {
			_, err = s.userAuthModel.Insert(ctx, session, &model.UserAuth{
				UserId:   normalUserID,
				AuthType: userTemp.AuthType,
				AuthKey:  userTemp.AuthKey,
			})
			if err != nil {
				return err
			}

			// 重新获取最新的userTemp数据，确保版本号是最新的
			latestUserTemp, err := s.userTempModel.FindOne(ctx, claims.UserId)
			if err != nil {
				return err
			}
			err = s.userTempModel.DeleteSoft(ctx, session, latestUserTemp)
			if err != nil {
				return err
			}
			return nil
		})
		if err != nil {
			return err
		}
		return nil
	} else {
		_, err = s.userAuthModel.Insert(ctx, session, &model.UserAuth{
			UserId:   normalUserID,
			AuthType: userTemp.AuthType,
			AuthKey:  userTemp.AuthKey,
		})
		if err != nil {
			return err
		}

		// 重新获取最新的userTemp数据，确保版本号是最新的
		latestUserTemp, err := s.userTempModel.FindOne(ctx, claims.UserId)
		if err != nil {
			return err
		}
		err = s.userTempModel.DeleteSoft(ctx, session, latestUserTemp)
		if err != nil {
			return err
		}
		return nil
	}
}

// _bak_RegisterUUIDUser 注册UUID用户，返回用户ID
func (s *UserService) _bak_RegisterUUIDUser(ctx context.Context) error {
	// 生成UUID
	uuidStr, err := s.GenerateUUIDUserId(ctx)
	if err != nil {
		return err
	}

	err = s.userTempModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error {
		// 创建用户临时记录
		userTemp := &model.UserTemp{
			AuthType: model.UserAuthTypeUUID,
			AuthKey:  uuidStr,
		}
		_, err := s.userTempModel.Insert(ctx, session, userTemp)
		return err
	})
	if err != nil {
		return err
	}

	return nil
}
