from typing import List, Dict, Any

class ComputeMarketplace:
    def __init__(self):
        # Initializing some mock idle nodes
        self.idle_nodes = [
            {"id": "node-1", "cpu": 8, "ram": 32, "price_per_hour": 0.05},
            {"id": "node-2", "cpu": 16, "ram": 64, "price_per_hour": 0.10},
            {"id": "node-3", "cpu": 4, "ram": 16, "price_per_hour": 0.02},
            {"id": "node-4", "cpu": 32, "ram": 128, "price_per_hour": 0.25},
        ]

    def list_idle_capacity(self, specs: Dict[str, Any]) -> List[Dict[str, Any]]:
        """List available idle nodes that meet the specified requirements."""
        min_cpu = specs.get("min_cpu", 0)
        min_ram = specs.get("min_ram", 0)
        max_price = specs.get("max_price", float("inf"))
        
        return [
            node for node in self.idle_nodes
            if node["cpu"] >= min_cpu and node["ram"] >= min_ram and node["price_per_hour"] <= max_price
        ]

    def bid_on_job(self, job: Dict[str, Any]) -> Dict[str, Any]:
        """Bid on a job given its requirements and max acceptable bid."""
        specs = job.get("specs", {})
        available_nodes = self.list_idle_capacity(specs)
        
        if not available_nodes:
            return {"status": "rejected", "reason": "No matching capacity"}
            
        # Select the cheapest available node that fits requirements
        selected_node = min(available_nodes, key=lambda x: x["price_per_hour"])
        
        max_bid = job.get("max_bid", float("inf"))
        if selected_node["price_per_hour"] > max_bid:
            return {"status": "rejected", "reason": "Bid too low"}
            
        return {
            "status": "accepted",
            "node_id": selected_node["id"],
            "price": selected_node["price_per_hour"]
        }
