package app

import (
	"errors"
	"time"

	"git.echol.cn/loser/st/server/global"
	"git.echol.cn/loser/st/server/model/app"
	"git.echol.cn/loser/st/server/model/app/request"
	"git.echol.cn/loser/st/server/model/app/response"
	"git.echol.cn/loser/st/server/utils"
	"github.com/google/uuid"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

type AuthService struct{}

// Register 用户注册
func (s *AuthService) Register(req *request.RegisterRequest) error {
	// 检查用户名是否已存在
	var count int64
	err := global.GVA_DB.Model(&app.AppUser{}).Where("username = ?", req.Username).Count(&count).Error
	if err != nil {
		return err
	}
	if count > 0 {
		return errors.New("用户名已存在")
	}

	// 检查邮箱是否已存在
	if req.Email != "" {
		err = global.GVA_DB.Model(&app.AppUser{}).Where("email = ?", req.Email).Count(&count).Error
		if err != nil {
			return err
		}
		if count > 0 {
			return errors.New("邮箱已被使用")
		}
	}

	// 密码加密
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		return errors.New("密码加密失败")
	}

	// 创建用户
	user := app.AppUser{
		UUID:     uuid.New().String(),
		Username: req.Username,
		Password: string(hashedPassword),
		NickName: req.NickName,
		Email:    req.Email,
		Phone:    req.Phone,
		Status:   "active",
		Enable:   true,
	}

	if user.NickName == "" {
		user.NickName = req.Username
	}

	return global.GVA_DB.Create(&user).Error
}

// Login 用户登录
func (s *AuthService) Login(req *request.LoginRequest, ip string) (*response.LoginResponse, error) {
	// 查询用户
	var user app.AppUser
	err := global.GVA_DB.Where("username = ?", req.Username).First(&user).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("用户名或密码错误")
		}
		return nil, err
	}

	// 检查用户状态
	if !user.Enable {
		return nil, errors.New("账户已被禁用")
	}
	if user.Status != "active" {
		return nil, errors.New("账户状态异常")
	}

	// 验证密码
	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password))
	if err != nil {
		return nil, errors.New("用户名或密码错误")
	}

	// 生成 Token
	token, expiresAt, err := utils.CreateAppToken(user.ID, user.Username)
	if err != nil {
		return nil, errors.New("Token 生成失败")
	}

	// 生成刷新 Token
	refreshToken, refreshExpiresAt, err := utils.CreateAppRefreshToken(user.ID, user.Username)
	if err != nil {
		return nil, errors.New("刷新 Token 生成失败")
	}

	// 更新最后登录信息
	now := time.Now()
	global.GVA_DB.Model(&user).Updates(map[string]interface{}{
		"last_login_at": now,
		"last_login_ip": ip,
	})

	// 保存会话信息（可选）
	session := app.AppUserSession{
		UserID:           user.ID,
		SessionToken:     token,
		RefreshToken:     refreshToken,
		ExpiresAt:        time.Unix(expiresAt, 0),
		RefreshExpiresAt: func() *time.Time { t := time.Unix(refreshExpiresAt, 0); return &t }(),
		IPAddress:        ip,
	}
	global.GVA_DB.Create(&session)

	return &response.LoginResponse{
		User:         response.ToAppUserResponse(&user),
		Token:        token,
		RefreshToken: refreshToken,
		ExpiresAt:    expiresAt,
	}, nil
}

// RefreshToken 刷新 Token
func (s *AuthService) RefreshToken(req *request.RefreshTokenRequest) (*response.LoginResponse, error) {
	// 解析刷新 Token
	claims, err := utils.ParseAppToken(req.RefreshToken)
	if err != nil {
		return nil, errors.New("刷新 Token 无效")
	}

	// 查询用户
	var user app.AppUser
	err = global.GVA_DB.Where("id = ?", claims.UserID).First(&user).Error
	if err != nil {
		return nil, errors.New("用户不存在")
	}

	// 检查用户状态
	if !user.Enable {
		return nil, errors.New("账户已被禁用")
	}

	// 生成新的 Token
	token, expiresAt, err := utils.CreateAppToken(user.ID, user.Username)
	if err != nil {
		return nil, errors.New("Token 生成失败")
	}

	// 生成新的刷新 Token
	refreshToken, _, err := utils.CreateAppRefreshToken(user.ID, user.Username)
	if err != nil {
		return nil, errors.New("刷新 Token 生成失败")
	}

	return &response.LoginResponse{
		User:         response.ToAppUserResponse(&user),
		Token:        token,
		RefreshToken: refreshToken,
		ExpiresAt:    expiresAt,
	}, nil
}

// Logout 用户登出
func (s *AuthService) Logout(userID uint, token string) error {
	// 删除会话记录
	return global.GVA_DB.Where("user_id = ? AND session_token = ?", userID, token).
		Delete(&app.AppUserSession{}).Error
}

// GetUserInfo 获取用户信息
func (s *AuthService) GetUserInfo(userID uint) (*response.AppUserResponse, error) {
	var user app.AppUser
	err := global.GVA_DB.Where("id = ?", userID).First(&user).Error
	if err != nil {
		return nil, err
	}

	resp := response.ToAppUserResponse(&user)
	return &resp, nil
}

// UpdateProfile 更新用户信息
func (s *AuthService) UpdateProfile(userID uint, req *request.UpdateProfileRequest) error {
	updates := make(map[string]interface{})

	if req.NickName != "" {
		updates["nick_name"] = req.NickName
	}
	if req.Email != "" {
		// 检查邮箱是否已被其他用户使用
		var count int64
		err := global.GVA_DB.Model(&app.AppUser{}).
			Where("email = ? AND id != ?", req.Email, userID).
			Count(&count).Error
		if err != nil {
			return err
		}
		if count > 0 {
			return errors.New("邮箱已被使用")
		}
		updates["email"] = req.Email
	}
	if req.Phone != "" {
		updates["phone"] = req.Phone
	}
	if req.Avatar != "" {
		updates["avatar"] = req.Avatar
	}
	if req.Preferences != "" {
		updates["preferences"] = req.Preferences
	}
	if req.AISettings != "" {
		updates["ai_settings"] = req.AISettings
	}

	if len(updates) == 0 {
		return nil
	}

	return global.GVA_DB.Model(&app.AppUser{}).Where("id = ?", userID).Updates(updates).Error
}

// ChangePassword 修改密码
func (s *AuthService) ChangePassword(userID uint, req *request.ChangePasswordRequest) error {
	// 查询用户
	var user app.AppUser
	err := global.GVA_DB.Where("id = ?", userID).First(&user).Error
	if err != nil {
		return err
	}

	// 验证旧密码
	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.OldPassword))
	if err != nil {
		return errors.New("原密码错误")
	}

	// 加密新密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
	if err != nil {
		return errors.New("密码加密失败")
	}

	// 更新密码
	return global.GVA_DB.Model(&user).Update("password", string(hashedPassword)).Error
}
