from typing import List, Dict, Any

class QuantumCircuit:
    """
    Object-oriented builder for Aṇu Astra 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."""
        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."""
        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."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "Z", "target": [target_qubit]})
        return self

    def s(self, target_qubit: int) -> 'QuantumCircuit':
        """Apply an S gate."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "S", "target": [target_qubit]})
        return self

    def sdg(self, target_qubit: int) -> 'QuantumCircuit':
        """Apply an S-dagger gate."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "Sdg", "target": [target_qubit]})
        return self

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

    def tdg(self, target_qubit: int) -> 'QuantumCircuit':
        """Apply a T-dagger gate."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "Tdg", "target": [target_qubit]})
        return self

    def sx(self, target_qubit: int) -> 'QuantumCircuit':
        """Apply a Square-Root-of-X gate."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "SX", "target": [target_qubit]})
        return self

    def sxdg(self, target_qubit: int) -> 'QuantumCircuit':
        """Apply a Square-Root-of-X-dagger gate."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "SXdg", "target": [target_qubit]})
        return self

    def id(self, target_qubit: int) -> 'QuantumCircuit':
        """Apply an Identity gate."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "ID", "target": [target_qubit]})
        return self


    def p(self, target_qubit: int, lambda_val: float) -> 'QuantumCircuit':
        """Apply a Phase gate."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "P", "target": [target_qubit], "param": float(lambda_val)})
        return self

    def rx(self, target_qubit: int, theta: float) -> 'QuantumCircuit':
        """Apply a parameterized rotation around the X-axis."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "RX", "target": [target_qubit], "param": float(theta)})
        return self

    def ry(self, target_qubit: int, theta: float) -> 'QuantumCircuit':
        """Apply a parameterized rotation around the Y-axis."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "RY", "target": [target_qubit], "param": float(theta)})
        return self

    def rz(self, target_qubit: int, theta: float) -> 'QuantumCircuit':
        """Apply a parameterized rotation around the Z-axis."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "RZ", "target": [target_qubit], "param": float(theta)})
        return self

    def u1(self, target_qubit: int, lambda_val: float) -> 'QuantumCircuit':
        """Apply a U1 gate (Phase)."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "U1", "target": [target_qubit], "param": float(lambda_val)})
        return self

    def u2(self, target_qubit: int, phi: float, lambda_val: float) -> 'QuantumCircuit':
        """Apply a U2 gate."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "U2", "target": [target_qubit], "params": [float(phi), float(lambda_val)]})
        return self

    def u3(self, target_qubit: int, theta: float, phi: float, lambda_val: float) -> 'QuantumCircuit':
        """Apply a general U3 gate."""
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "U3", "target": [target_qubit], "params": [float(theta), float(phi), float(lambda_val)]})
        return self

    def u(self, target_qubit: int, theta: float, phi: float, lambda_val: float) -> 'QuantumCircuit':
        """Alias for U3."""
        return self.u3(target_qubit, theta, phi, lambda_val)


    def cnot(self, control_qubit: int, target_qubit: int) -> 'QuantumCircuit':
        """Apply a Controlled-NOT (CNOT) gate."""
        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 CNOT."""
        return self.cnot(control_qubit, target_qubit)

    def cz(self, control_qubit: int, target_qubit: int) -> 'QuantumCircuit':
        """Apply a Controlled-Z gate."""
        self._validate_qubit(control_qubit)
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "CZ", "target": [control_qubit, target_qubit]})
        return self

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

    def ch(self, control_qubit: int, target_qubit: int) -> 'QuantumCircuit':
        """Apply a Controlled-Hadamard gate."""
        self._validate_qubit(control_qubit)
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "CH", "target": [control_qubit, target_qubit]})
        return self

    def swap(self, q1: int, q2: int) -> 'QuantumCircuit':
        """Apply a SWAP gate."""
        self._validate_qubit(q1)
        self._validate_qubit(q2)
        self.operations.append({"gate": "SWAP", "target": [q1, q2]})
        return self

    def iswap(self, q1: int, q2: int) -> 'QuantumCircuit':
        """Apply an iSWAP gate."""
        self._validate_qubit(q1)
        self._validate_qubit(q2)
        self.operations.append({"gate": "iSWAP", "target": [q1, q2]})
        return self

    def ecr(self, q1: int, q2: int) -> 'QuantumCircuit':
        """Apply an Echoed Cross-Resonator gate."""
        self._validate_qubit(q1)
        self._validate_qubit(q2)
        self.operations.append({"gate": "ECR", "target": [q1, q2]})
        return self

    def dcx(self, q1: int, q2: int) -> 'QuantumCircuit':
        """Apply a Double CNOT gate."""
        self._validate_qubit(q1)
        self._validate_qubit(q2)
        self.operations.append({"gate": "DCX", "target": [q1, q2]})
        return self


    def crx(self, control_qubit: int, target_qubit: int, theta: float) -> 'QuantumCircuit':
        """Apply a Controlled-RX gate."""
        self._validate_qubit(control_qubit)
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "CRX", "target": [control_qubit, target_qubit], "param": float(theta)})
        return self

    def cry(self, control_qubit: int, target_qubit: int, theta: float) -> 'QuantumCircuit':
        """Apply a Controlled-RY gate."""
        self._validate_qubit(control_qubit)
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "CRY", "target": [control_qubit, target_qubit], "param": float(theta)})
        return self

    def crz(self, control_qubit: int, target_qubit: int, theta: float) -> 'QuantumCircuit':
        """Apply a Controlled-RZ gate."""
        self._validate_qubit(control_qubit)
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "CRZ", "target": [control_qubit, target_qubit], "param": float(theta)})
        return self

    def cp(self, control_qubit: int, target_qubit: int, lambda_val: float) -> 'QuantumCircuit':
        """Apply a Controlled-Phase gate."""
        self._validate_qubit(control_qubit)
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "CP", "target": [control_qubit, target_qubit], "param": float(lambda_val)})
        return self

    def cu(self, control_qubit: int, target_qubit: int, theta: float, phi: float, lambda_val: float, gamma: float) -> 'QuantumCircuit':
        """Apply a Controlled-Unitary gate."""
        self._validate_qubit(control_qubit)
        self._validate_qubit(target_qubit)
        self.operations.append({"gate": "CU", "target": [control_qubit, target_qubit], "params": [float(theta), float(phi), float(lambda_val), float(gamma)]})
        return self

    def rxx(self, q1: int, q2: int, theta: float) -> 'QuantumCircuit':
        """Apply an RXX gate."""
        self._validate_qubit(q1)
        self._validate_qubit(q2)
        self.operations.append({"gate": "RXX", "target": [q1, q2], "param": float(theta)})
        return self

    def ryy(self, q1: int, q2: int, theta: float) -> 'QuantumCircuit':
        """Apply an RYY gate."""
        self._validate_qubit(q1)
        self._validate_qubit(q2)
        self.operations.append({"gate": "RYY", "target": [q1, q2], "param": float(theta)})
        return self

    def rzz(self, q1: int, q2: int, theta: float) -> 'QuantumCircuit':
        """Apply an RZZ gate."""
        self._validate_qubit(q1)
        self._validate_qubit(q2)
        self.operations.append({"gate": "RZZ", "target": [q1, q2], "param": float(theta)})
        return self

    def rzx(self, q1: int, q2: int, theta: float) -> 'QuantumCircuit':
        """Apply an RZX gate."""
        self._validate_qubit(q1)
        self._validate_qubit(q2)
        self.operations.append({"gate": "RZX", "target": [q1, q2], "param": float(theta)})
        return self


    def ccx(self, q1: int, q2: int, q3: int) -> 'QuantumCircuit':
        """Apply a Toffoli (CCX) gate."""
        self._validate_qubit(q1)
        self._validate_qubit(q2)
        self._validate_qubit(q3)
        self.operations.append({"gate": "Toffoli", "target": [q1, q2, q3]})
        return self

    def toffoli(self, q1: int, q2: int, q3: int) -> 'QuantumCircuit':
        """Alias for CCX."""
        return self.ccx(q1, q2, q3)

    def ccz(self, q1: int, q2: int, q3: int) -> 'QuantumCircuit':
        """Apply a Controlled-Controlled-Z gate."""
        self._validate_qubit(q1)
        self._validate_qubit(q2)
        self._validate_qubit(q3)
        self.operations.append({"gate": "CCZ", "target": [q1, q2, q3]})
        return self

    def fredkin(self, q1: int, q2: int, q3: int) -> 'QuantumCircuit':
        """Apply a Fredkin (CSWAP) gate."""
        self._validate_qubit(q1)
        self._validate_qubit(q2)
        self._validate_qubit(q3)
        self.operations.append({"gate": "Fredkin", "target": [q1, q2, q3]})
        return self

    def cswap(self, q1: int, q2: int, q3: int) -> 'QuantumCircuit':
        """Alias for Fredkin."""
        return self.fredkin(q1, q2, q3)

    def c3x(self, q1: int, q2: int, q3: int, q4: int) -> 'QuantumCircuit':
        """Apply a Triple-Controlled-X gate."""
        self._validate_qubit(q1)
        self._validate_qubit(q2)
        self._validate_qubit(q3)
        self._validate_qubit(q4)
        self.operations.append({"gate": "C3X", "target": [q1, q2, q3, q4]})
        return self

    def c4x(self, q1: int, q2: int, q3: int, q4: int, q5: int) -> 'QuantumCircuit':
        """Apply a Quadruple-Controlled-X gate."""
        self._validate_qubit(q1)
        self._validate_qubit(q2)
        self._validate_qubit(q3)
        self._validate_qubit(q4)
        self._validate_qubit(q5)
        self.operations.append({"gate": "QuadX", "target": [q1, q2, q3, q4, q5]})
        return self

    def quadx(self, q1: int, q2: int, q3: int, q4: int, q5: int) -> 'QuantumCircuit':
        """Alias for C4X."""
        return self.c4x(q1, q2, q3, q4, q5)

    def measure(self, target_qubit: int) -> 'QuantumCircuit':
        """Measure a specific qubit. (Implicit in Aṇu Astra)"""
        self._validate_qubit(target_qubit)
        return self

    def measure_all(self) -> 'QuantumCircuit':
        """Measure all qubits."""
        return self

