from typing import List, Dict, Any

class QuantumCircuit:
    """
    Object-oriented builder for AnuAstra quantum physics execution.
    Mirrors the industry-standard DX of IBM Qiskit and Google Cirq.
    """
    def __init__(self, qubits: int):
        if qubits <= 0:
            raise ValueError("A QuantumCircuit must have at least 1 qubit.")
        self.qubits = qubits
        self.operations: List[Dict[str, Any]] = []

    def _validate_qubit(self, q: int):
        if q < 0 or q >= self.qubits:
            raise ValueError(f"Qubit index {q} is out of bounds for a {self.qubits}-qubit circuit.")

    def h(self, target_qubit: int) -> 'QuantumCircuit':
        """Apply a Hadamard gate to put a qubit into superposition."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "H", "target": [target_qubit]})
        return self

    def x(self, target_qubit: int) -> 'QuantumCircuit':
        """Apply a Pauli-X (NOT) gate to flip a qubit's state."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "X", "target": [target_qubit]})
        return self

    def y(self, target_qubit: int) -> 'QuantumCircuit':
        """Apply a Pauli-Y gate."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "Y", "target": [target_qubit]})
        return self

    def z(self, target_qubit: int) -> 'QuantumCircuit':
        """Apply a Pauli-Z gate (Phase flip)."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "Z", "target": [target_qubit]})
        return self

    def cnot(self, control_qubit: int, target_qubit: int) -> 'QuantumCircuit':
        """Apply a Controlled-NOT (CNOT) gate to entangle two qubits."""
        self._validate_qubit(control_qubit)
        self._validate_qubit(target_qubit)
        if control_qubit == target_qubit:
            raise ValueError("Control and Target qubits cannot be the same.")
        self.operations.append({"gate": "CNOT", "target": [control_qubit, target_qubit]})
        return self

    def cx(self, control_qubit: int, target_qubit: int) -> 'QuantumCircuit':
        """Alias for Qiskit familiarity."""
        return self.cnot(control_qubit, target_qubit)

    def t(self, target_qubit: int) -> 'QuantumCircuit':
        """Apply a T-Gate (Pi/4 Phase)."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "T", "target": [target_qubit]})
        return self
