```python
from collections import defaultdict

def apply_charges(caps: dict, charges: list) -> dict:
    """Return an object with left (remaining allowances) and refused (refused charges)."""
    if not all(isinstance(v[0], int) and isinstance(v[1], int) for v in caps.values()):
        raise ValueError("Invalid quota values")
    
    remaining = {bucket: allowance for bucket, (allowance, _) in caps.items()}
    refused = []
    
    for charge_id, bucket_name, amount in charges:
        if not isinstance(charge_id, int) or not isinstance(bucket_name, str) or not isinstance(amount, int):
            raise ValueError("Invalid charge format")
        
        if amount <= 0:
            raise ValueError("Amount must be a positive whole number")
        
        if bucket_name not in remaining:
            refused.append((charge_id, "unknown"))
            continue
        
        if amount > caps[bucket_name][1]:
            refused.append((charge_id, "single"))
            continue
        
        if amount > remaining[bucket_name]:
            refused.append((charge_id, "cap"))
            continue
        
        remaining[bucket_name] -= amount
    
    return {"left": remaining, "refused": refused}
```