package mysql

import (
	"context"
	"database/sql"
	"errors"
	"strings"

	"hyapp/pkg/appcode"
	roomservice "hyapp/services/room-service/internal/room/service"
)

// ListRoomDecorationAssignments 只扫描装扮专用反向索引，并使用稳定 room_id/type 游标分页。
// resource/user 事件分别命中对应复合索引；VipProgramChanged 才会按主键遍历该低频小表。
func (r *Repository) ListRoomDecorationAssignments(ctx context.Context, query roomservice.RoomDecorationAssignmentQuery) ([]roomservice.RoomDecorationAssignment, error) {
	limit := query.Limit
	if limit <= 0 || limit > 500 {
		limit = 100
	}
	args := []any{appcode.FromContext(ctx)}
	statement := `SELECT app_code, room_id, decoration_type, owner_user_id, benefit_code,
		resource_id, entitlement_id, expires_at_ms, updated_at_ms
		FROM room_decoration_assignments WHERE app_code = ?`
	switch {
	case query.ResourceID > 0:
		statement += ` AND resource_id = ?`
		args = append(args, query.ResourceID)
	case query.OwnerUserID > 0:
		statement += ` AND owner_user_id = ?`
		args = append(args, query.OwnerUserID)
	}
	if strings.TrimSpace(query.AfterRoomID) != "" {
		statement += ` AND (room_id > ? OR (room_id = ? AND decoration_type > ?))`
		args = append(args, strings.TrimSpace(query.AfterRoomID), strings.TrimSpace(query.AfterRoomID), strings.TrimSpace(query.AfterDecorationType))
	}
	statement += ` ORDER BY room_id ASC, decoration_type ASC LIMIT ?`
	args = append(args, limit)
	rows, err := r.db.QueryContext(ctx, statement, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	assignments := make([]roomservice.RoomDecorationAssignment, 0, limit)
	for rows.Next() {
		var assignment roomservice.RoomDecorationAssignment
		if err := rows.Scan(
			&assignment.AppCode, &assignment.RoomID, &assignment.DecorationType, &assignment.OwnerUserID,
			&assignment.BenefitCode, &assignment.ResourceID, &assignment.EntitlementID,
			&assignment.ExpiresAtMS, &assignment.UpdatedAtMS,
		); err != nil {
			return nil, err
		}
		assignments = append(assignments, assignment)
	}
	return assignments, rows.Err()
}

func (r *Repository) HasConsumedWalletDecorationEvent(ctx context.Context, eventID string) (bool, error) {
	var value int
	err := r.db.QueryRowContext(ctx, `
		SELECT 1 FROM room_wallet_event_consumption
		WHERE app_code = ? AND event_id = ? LIMIT 1`,
		appcode.FromContext(ctx), strings.TrimSpace(eventID),
	).Scan(&value)
	if errors.Is(err, sql.ErrNoRows) {
		return false, nil
	}
	return err == nil, err
}

// MarkWalletDecorationEventConsumed 只在该事件所有目标房间均已幂等提交后调用。
func (r *Repository) MarkWalletDecorationEventConsumed(ctx context.Context, eventID string, eventType string, consumedAtMS int64) error {
	_, err := r.db.ExecContext(ctx, `
		INSERT INTO room_wallet_event_consumption (app_code, event_id, event_type, consumed_at_ms)
		VALUES (?, ?, ?, ?)
		ON DUPLICATE KEY UPDATE event_id = room_wallet_event_consumption.event_id`,
		appcode.FromContext(ctx), strings.TrimSpace(eventID), strings.TrimSpace(eventType), consumedAtMS)
	return err
}
