package roomrobot

import (
	"context"
	"strings"
	"time"

	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
	robotdomain "hyapp/services/robot-service/internal/domain/robot"
)

// Repository 是 room-robot 用例层的持久化边界；首版只管理房间机器人账号池，不直接操作 Room Cell 内的房间状态。
type Repository interface {
	PickRoomRobot(ctx context.Context, appCode string, roomScene string, roomID string, nowMS int64) (robotdomain.Robot, error)
	ListRoomRobots(ctx context.Context, appCode string, roomScene string, status string, pageSize int32, cursor string) ([]robotdomain.Robot, string, error)
	RegisterRoomRobots(ctx context.Context, appCode string, roomScene string, userIDs []int64, adminID int64, nowMS int64) ([]robotdomain.Robot, error)
	SetRoomRobotStatus(ctx context.Context, appCode string, roomScene string, userID int64, status string, nowMS int64) (robotdomain.Robot, error)
	DeleteRoomRobot(ctx context.Context, appCode string, roomScene string, userID int64) error
}

// Service 管理房间机器人账号池；未来房间侧需要机器人入房时，也应该由 room-service 请求这里拿账号后再由 Room Cell 执行动作。
type Service struct {
	repo Repository
	now  func() time.Time
}

func New(repo Repository) *Service {
	return &Service{repo: repo, now: time.Now}
}

func (s *Service) ListRobots(ctx context.Context, appCode string, roomScene string, status string, pageSize int32, cursor string) ([]robotdomain.Robot, string, int64, error) {
	if s == nil || s.repo == nil {
		return nil, "", 0, xerr.New(xerr.Unavailable, "room robot repository is not configured")
	}
	app := appcode.Normalize(appCode)
	ctx = appcode.WithContext(ctx, app)
	items, next, err := s.repo.ListRoomRobots(ctx, app, roomScene, strings.TrimSpace(status), pageSize, cursor)
	return items, next, s.now().UnixMilli(), err
}

func (s *Service) RegisterRobots(ctx context.Context, appCode string, roomScene string, userIDs []int64, adminID int64) ([]robotdomain.Robot, int64, error) {
	if s == nil || s.repo == nil {
		return nil, 0, xerr.New(xerr.Unavailable, "room robot repository is not configured")
	}
	if len(userIDs) == 0 {
		return nil, 0, xerr.New(xerr.InvalidArgument, "room robot user_ids is required")
	}
	app := appcode.Normalize(appCode)
	ctx = appcode.WithContext(ctx, app)
	nowMS := s.now().UnixMilli()
	items, err := s.repo.RegisterRoomRobots(ctx, app, roomScene, userIDs, adminID, nowMS)
	return items, nowMS, err
}

func (s *Service) PickRobot(ctx context.Context, appCode string, roomScene string, roomID string, selectedAtMS int64) (robotdomain.Robot, int64, error) {
	if s == nil || s.repo == nil {
		return robotdomain.Robot{}, 0, xerr.New(xerr.Unavailable, "room robot repository is not configured")
	}
	app := appcode.Normalize(appCode)
	ctx = appcode.WithContext(ctx, app)
	nowMS := selectedAtMS
	if nowMS <= 0 {
		nowMS = s.now().UnixMilli()
	}
	item, err := s.repo.PickRoomRobot(ctx, app, roomScene, roomID, nowMS)
	return item, nowMS, err
}

func (s *Service) SetRobotStatus(ctx context.Context, appCode string, roomScene string, userID int64, status string) (robotdomain.Robot, int64, error) {
	if s == nil || s.repo == nil {
		return robotdomain.Robot{}, 0, xerr.New(xerr.Unavailable, "room robot repository is not configured")
	}
	if userID <= 0 {
		return robotdomain.Robot{}, 0, xerr.New(xerr.InvalidArgument, "room robot user_id is invalid")
	}
	app := appcode.Normalize(appCode)
	ctx = appcode.WithContext(ctx, app)
	nowMS := s.now().UnixMilli()
	item, err := s.repo.SetRoomRobotStatus(ctx, app, roomScene, userID, status, nowMS)
	return item, nowMS, err
}

func (s *Service) DeleteRobot(ctx context.Context, appCode string, roomScene string, userID int64) (int64, error) {
	if s == nil || s.repo == nil {
		return 0, xerr.New(xerr.Unavailable, "room robot repository is not configured")
	}
	if userID <= 0 {
		return 0, xerr.New(xerr.InvalidArgument, "room robot user_id is invalid")
	}
	app := appcode.Normalize(appCode)
	ctx = appcode.WithContext(ctx, app)
	nowMS := s.now().UnixMilli()
	return nowMS, s.repo.DeleteRoomRobot(ctx, app, roomScene, userID)
}
