package service

import (
	"context"
	"errors"

	"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
	domain_notify "git.huangwc.com/pig/pig-farm-controller/internal/domain/notify"
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/utils/token"

	"gorm.io/gorm"
)

// UserService 定义用户服务接口
type UserService interface {
	CreateUser(ctx context.Context, req *dto.CreateUserRequest) (*dto.CreateUserResponse, error)
	Login(ctx context.Context, req *dto.LoginRequest) (*dto.LoginResponse, error)
	SendTestNotification(ctx context.Context, userID uint32, req *dto.SendTestNotificationRequest) error
}

// userService 实现了 UserService 接口
type userService struct {
	ctx            context.Context
	userRepo       repository.UserRepository
	tokenGenerator token.Generator
	notifyService  domain_notify.Service
}

// NewUserService 创建并返回一个新的 UserService 实例
func NewUserService(
	ctx context.Context,
	userRepo repository.UserRepository,
	tokenGenerator token.Generator,
	notifyService domain_notify.Service,
) UserService {
	return &userService{
		ctx:            ctx,
		userRepo:       userRepo,
		tokenGenerator: tokenGenerator,
		notifyService:  notifyService,
	}
}

// CreateUser 创建新用户
func (s *userService) CreateUser(ctx context.Context, req *dto.CreateUserRequest) (*dto.CreateUserResponse, error) {
	serviceCtx, logger := logs.Trace(ctx, s.ctx, "CreateUser")
	user := &models.User{
		Username: req.Username,
		Password: req.Password, // 密码会在 BeforeSave 钩子中哈希
	}

	if err := s.userRepo.Create(serviceCtx, user); err != nil {
		logger.Errorf("创建用户: 创建用户失败: %v", err)

		// 尝试查询用户，以判断是否是用户名重复导致的错误
		_, findErr := s.userRepo.FindByUsername(serviceCtx, req.Username)
		if findErr == nil { // 如果能找到用户，说明是用户名重复
			return nil, errors.New("用户名已存在")
		}

		// 其他创建失败的情况
		return nil, errors.New("创建用户失败")
	}

	return &dto.CreateUserResponse{
		Username: user.Username,
		ID:       user.ID,
	}, nil
}

// Login 用户登录
func (s *userService) Login(ctx context.Context, req *dto.LoginRequest) (*dto.LoginResponse, error) {
	serviceCtx, logger := logs.Trace(ctx, s.ctx, "Login")
	// 使用新的方法，通过唯一标识符（用户名、邮箱等）查找用户
	user, err := s.userRepo.FindUserForLogin(serviceCtx, req.Identifier)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("登录凭证不正确")
		}
		logger.Errorf("登录: 查询用户失败: %v", err)
		return nil, errors.New("登录失败")
	}

	if !user.CheckPassword(req.Password) {
		return nil, errors.New("登录凭证不正确")
	}

	// 登录成功，生成 JWT token
	tokenString, err := s.tokenGenerator.GenerateToken(user.ID)
	if err != nil {
		logger.Errorf("登录: 生成令牌失败: %v", err)
		return nil, errors.New("登录失败，无法生成认证信息")
	}

	return &dto.LoginResponse{
		Username: user.Username,
		ID:       user.ID,
		Token:    tokenString,
	}, nil
}

// SendTestNotification 发送测试通知
func (s *userService) SendTestNotification(ctx context.Context, userID uint32, req *dto.SendTestNotificationRequest) error {
	serviceCtx, logger := logs.Trace(ctx, s.ctx, "SendTestNotification")
	err := s.notifyService.SendTestMessage(serviceCtx, userID, req.Type)
	if err != nil {
		logger.Errorf("发送测试通知: 服务层调用失败: %v", err)
		return errors.New("发送测试消息失败: " + err.Error())
	}
	logger.Infof("发送测试通知: 成功为用户 %d 发送类型为 %s 的测试消息", userID, req.Type)
	return nil
}
