package service

import (
	"crypto/rand"
	"encoding/base64"
	"errors"

	"git.zkcoi.com/zkcoi/meshray/internal/model"
	"git.zkcoi.com/zkcoi/meshray/internal/store/sqlite"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

// 字符集用于生成随机密码（保留用于特殊场景）
const passwordChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*"

// generateRandomPassword 使用 crypto/rand 生成安全的随机密码
func generateRandomPassword(length int) string {
	b := make([]byte, length)
	_, err := rand.Read(b)
	if err != nil {
		// 极端情况下回退到简单方案（几乎不会发生）
		return "REPLACE_WITH_SECURE_PASSWORD"
	}
	// 使用 Base64 编码，确保包含各种字符
	encoded := base64.StdEncoding.EncodeToString(b)
	// 截取所需长度（Base64 编码后长度为 4/3 倍）
	if len(encoded) >= length {
		return encoded[:length]
	}
	return encoded
}

// GenerateRandomPassword 生成随机密码（公开函数）
func GenerateRandomPassword(length int) string {
	return generateRandomPassword(length)
}

// UserService 用户服务
type UserService struct {
	store *sqlite.Store
}

// NewUserService 创建用户服务实例
func NewUserService(store *sqlite.Store) *UserService {
	return &UserService{store: store}
}

// InitializeAdmin 初始化管理员账户（首次启动时调用）
func (s *UserService) InitializeAdmin() (username, password string, err error) {
	// 检查是否已存在 admin 用户
	var existingUser model.User
	if err := s.store.DB().Where("role = ?", "admin").First(&existingUser).Error; err == nil {
		// 已存在，返回当前用户名（密码不返回）
		return existingUser.Username, "", nil
	}

	// 生成随机密码
	randomPassword := generateRandomPassword(16)

	// 密码加密
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(randomPassword), bcrypt.DefaultCost)
	if err != nil {
		return "", "", err
	}

	// 创建 admin 用户
	adminUser := &model.User{
		Username:     "admin",
		PasswordHash: string(hashedPassword),
		Email:        "",
		Role:         "admin",
		Status:       "active",
	}

	if err := s.store.DB().Create(adminUser).Error; err != nil {
		return "", "", err
	}

	return "admin", randomPassword, nil
}

// Authenticate 验证用户登录
func (s *UserService) Authenticate(username, password string) (*model.User, error) {
	var user model.User
	if err := s.store.DB().Where("username = ?", username).First(&user).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("用户不存在")
		}
		return nil, err
	}

	// 验证密码
	if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(password)); err != nil {
		return nil, errors.New("密码错误")
	}

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

	return &user, nil
}

// ChangePasswordRequest 修改密码请求
type ChangePasswordRequest struct {
	OldPassword string `json:"old_password"`
	NewPassword string `json:"new_password"`
}

// ChangePassword 修改用户密码
func (s *UserService) ChangePassword(userID uint, req *ChangePasswordRequest) error {
	// 1. 查询用户
	var user model.User
	if err := s.store.DB().First(&user, userID).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("用户不存在")
		}
		return err
	}

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

	// 3. 验证新密码强度
	if len(req.NewPassword) < 6 {
		return errors.New("密码长度不能少于 6 位")
	}

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

	// 5. 更新密码
	user.PasswordHash = string(hashedPassword)
	if err := s.store.DB().Save(&user).Error; err != nil {
		return err
	}

	return nil
}

// GetUserByID 根据 ID 获取用户
func (s *UserService) GetUserByID(userID uint) (*model.User, error) {
	var user model.User
	if err := s.store.DB().First(&user, userID).Error; err != nil {
		return nil, err
	}
	return &user, nil
}

// UpdateUser 更新用户信息
func (s *UserService) UpdateUser(userID uint, updates map[string]interface{}) (*model.User, error) {
	var user model.User
	if err := s.store.DB().First(&user, userID).Error; err != nil {
		return nil, err
	}

	if err := s.store.DB().Model(&user).Updates(updates).Error; err != nil {
		return nil, err
	}

	return &user, nil
}

// UpdateAdminProfile 更新管理员资料（仅允许 admin 用户调用）
func (s *UserService) UpdateAdminProfile(username, email, password string) error {
	var user model.User
	if err := s.store.DB().Where("role = ?", "admin").First(&user).Error; err != nil {
		return errors.New("管理员账户不存在")
	}

	updates := make(map[string]interface{})
	if username != "" && username != user.Username {
		// 检查新用户名是否已被使用
		var existing model.User
		if err := s.store.DB().Where("username = ? AND role = ?", username, "admin").First(&existing).Error; err == nil {
			return errors.New("用户名已存在")
		}
		updates["username"] = username
	}

	if email != "" && email != user.Email {
		updates["email"] = email
	}

	if password != "" {
		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
		if err != nil {
			return err
		}
		updates["password_hash"] = string(hashedPassword)
	}

	if len(updates) == 0 {
		return nil // 没有需要更新的
	}

	return s.store.DB().Model(&user).Updates(updates).Error
}

// ResetAdminPassword 重置管理员密码（命令行工具使用）
func (s *UserService) ResetAdminPassword(newPassword string) error {
	var user model.User
	if err := s.store.DB().Where("role = ?", "admin").First(&user).Error; err != nil {
		return errors.New("管理员账户不存在")
	}

	// 加密新密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	return s.store.DB().Model(&user).Update("password_hash", string(hashedPassword)).Error
}
