# (C) Copyright IBM 2024.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""POVMMetadata."""

from __future__ import annotations

import dataclasses
from dataclasses import dataclass

import numpy as np
from qiskit.circuit import QuantumCircuit

from ..povm_implementation import POVMImplementation


@dataclass
class POVMMetadata:
    """The bare metadata container for POVM sampling results."""

    povm_implementation: POVMImplementation
    """The POVM implementation which produced the results to which this metadata belongs."""

    composed_circuit: QuantumCircuit
    """The quantum circuit which produced the results to which this metadata belongs.

    This circuit is the composition of the quantum circuit specified by a PUB and the
    measurement circuit generated by the POVM implementation used. This is the quantum
    circuit that is eventually sent to the internal :class:`.BaseSamplerV2`.
    """

    def __repr__(self) -> str:
        """Implement the default ``__repr__`` method to avoid printing large objects.

        E.g., the attribute ``composed_circuit`` is a quantum circuit. With the default
        ``dataclass.__repr__``, it would be entirely drawn. As this is recursive,
        the full circuit would be printed when printing the :class:`.PrimitiveResult`
        object returned by the :meth:`.POVMSampler.run` method. The redefinition
        here avoids this.
        """
        lst_fields = []
        for field in dataclasses.fields(self):
            f_name = field.name
            f_val = getattr(self, field.name)
            if isinstance(f_val, np.ndarray):
                f_val = f'np.ndarray<{",".join(map(str, f_val.shape))}>'
            elif isinstance(f_val, QuantumCircuit):
                f_val = f_val.__repr__()
            lst_fields.append((f_name, f_val))
        f_repr = ", ".join(f"{name}={value}" for name, value in lst_fields)
        return f"{self.__class__.__name__}({f_repr})"
