package service

import (
	"context"
	"errors"
	"strings"

	"github.com/user-management-system/internal/auth"
	"github.com/user-management-system/internal/domain"
)

var ErrAdminBootstrapUnavailable = errors.New("管理员初始化入口已关闭")

type BootstrapAdminRequest struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
	Email    string `json:"email"`
	Nickname string `json:"nickname"`
}

func (s *AuthService) BootstrapAdmin(ctx context.Context, req *BootstrapAdminRequest, ip string) (*LoginResponse, error) {
	if req == nil {
		return nil, errors.New("管理员初始化请求不能为空")
	}
	if s == nil || s.userRepo == nil || s.userRoleRepo == nil || s.roleRepo == nil || s.jwtManager == nil {
		return nil, errors.New("管理员初始化能力未正确配置")
	}
	if !s.IsAdminBootstrapRequired(ctx) {
		return nil, ErrAdminBootstrapUnavailable
	}

	username := strings.TrimSpace(req.Username)
	email := strings.TrimSpace(req.Email)
	nickname := strings.TrimSpace(req.Nickname)

	if username == "" {
		return nil, errors.New("用户名不能为空")
	}
	if strings.TrimSpace(req.Password) == "" {
		return nil, errors.New("密码不能为空")
	}
	if err := s.validatePassword(req.Password); err != nil {
		return nil, err
	}

	exists, err := s.userRepo.ExistsByUsername(ctx, username)
	if err != nil {
		return nil, err
	}
	if exists {
		return nil, errors.New("用户名已存在")
	}

	if email != "" {
		exists, err = s.userRepo.ExistsByEmail(ctx, email)
		if err != nil {
			return nil, err
		}
		if exists {
			return nil, errors.New("邮箱已存在")
		}
	}

	adminRole, err := s.roleRepo.GetByCode(ctx, adminRoleCode)
	if err != nil {
		return nil, err
	}
	if adminRole == nil || adminRole.Status != domain.RoleStatusEnabled {
		return nil, errors.New("管理员角色不可用")
	}

	passwordHash, err := auth.HashPassword(req.Password)
	if err != nil {
		return nil, err
	}

	if nickname == "" {
		nickname = username
	}

	user := &domain.User{
		Username: username,
		Email:    domain.StrPtr(email),
		Password: passwordHash,
		Nickname: nickname,
		Status:   domain.UserStatusActive,
	}
	if err := s.userRepo.Create(ctx, user); err != nil {
		return nil, err
	}

	if err := s.userRoleRepo.BatchCreate(ctx, []*domain.UserRole{
		{UserID: user.ID, RoleID: adminRole.ID},
	}); err != nil {
		_ = s.userRepo.Delete(ctx, user.ID)
		return nil, err
	}

	s.bestEffortUpdateLastLogin(ctx, user.ID, ip, "admin_bootstrap")
	s.cacheUserInfo(ctx, user)
	s.writeLoginLog(ctx, &user.ID, domain.LoginTypePassword, ip, true, "")
	s.publishEvent(ctx, domain.EventUserRegistered, map[string]interface{}{
		"user_id":  user.ID,
		"username": user.Username,
		"role":     adminRoleCode,
		"source":   "admin_bootstrap",
	})
	s.publishEvent(ctx, domain.EventUserLogin, map[string]interface{}{
		"user_id":  user.ID,
		"username": user.Username,
		"ip":       ip,
		"method":   "admin_bootstrap",
	})

	return s.generateLoginResponseWithoutRemember(ctx, user)
}
