package identity

import (
	"context"
	"fmt"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/store/model"
)

// ListActiveMobileSessions returns the caller's currently usable miniapp
// session families. The query is scoped by user and backed by the
// user_session_families_user_client_active_idx index.
func (store *Store) ListActiveMobileSessions(ctx context.Context, userID string) ([]model.MobileSession, error) {
	rows, err := store.db.Query(ctx, `
SELECT id, device_name, device_platform, expires_at, created_at
FROM user_session_families
WHERE user_id = $1
  AND client_type = 'miniapp'
  AND revoked_at IS NULL
  AND expires_at > NOW()
ORDER BY created_at DESC, id DESC
LIMIT 20
`, userID)
	if err != nil {
		return nil, fmt.Errorf("list active mobile sessions: %w", err)
	}
	defer rows.Close()

	sessions := make([]model.MobileSession, 0)
	for rows.Next() {
		var session model.MobileSession
		if err := rows.Scan(
			&session.ID,
			&session.DeviceName,
			&session.DevicePlatform,
			&session.ExpiresAt,
			&session.CreatedAt,
		); err != nil {
			return nil, fmt.Errorf("scan active mobile session: %w", err)
		}
		sessions = append(sessions, session)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate active mobile sessions: %w", err)
	}
	return sessions, nil
}

// RevokeMobileSession revokes one miniapp session family owned by userID.
// Access and refresh authentication both consult the family, so revocation
// takes effect without updating every rotated child token row.
func (store *Store) RevokeMobileSession(ctx context.Context, userID string, sessionFamilyID string) error {
	now := time.Now().UTC()
	result, err := store.db.Exec(ctx, `
UPDATE user_session_families
SET revoked_at = $3
WHERE id = $1
  AND user_id = $2
  AND client_type = 'miniapp'
  AND revoked_at IS NULL
`, sessionFamilyID, userID, now)
	if err != nil {
		return fmt.Errorf("revoke mobile session: %w", err)
	}
	if result.RowsAffected() == 0 {
		return notFound("mobile session not found")
	}
	return nil
}
