"""
Base backend interface for computational operations.
"""

from abc import ABC, abstractmethod
from typing import Tuple, Optional, Union
import numpy as np


class BaseBackend(ABC):
    """Abstract base class for computational backends."""
    
    @property
    @abstractmethod
    def name(self) -> str:
        """Backend name."""
        pass
    
    @abstractmethod
    def to_array(self, data, dtype=None):
        """Convert data to backend array type."""
        pass
    
    @abstractmethod
    def to_numpy(self, data) -> np.ndarray:
        """Convert backend array to numpy."""
        pass
    
    @abstractmethod
    def zeros(self, shape, dtype=None):
        """Create zero array."""
        pass
    
    @abstractmethod
    def ones(self, shape, dtype=None):
        """Create ones array."""
        pass
    
    @abstractmethod
    def eye(self, n: int, dtype=None):
        """Create identity matrix."""
        pass
    
    @abstractmethod
    def arange(self, start, stop=None, step=1, dtype=None):
        """Create range array."""
        pass
    
    @abstractmethod
    def linspace(self, start, stop, num: int):
        """Create linearly spaced array."""
        pass
    
    @abstractmethod
    def concatenate(self, arrays, axis=0):
        """Concatenate arrays."""
        pass
    
    @abstractmethod
    def stack(self, arrays, axis=0):
        """Stack arrays."""
        pass
    
    # Linear algebra operations
    @abstractmethod
    def matmul(self, a, b):
        """Matrix multiplication."""
        pass
    
    @abstractmethod
    def eigh(self, a) -> Tuple:
        """Eigenvalue decomposition for Hermitian matrices."""
        pass
    
    @abstractmethod
    def eig(self, a) -> Tuple:
        """General eigenvalue decomposition."""
        pass
    
    @abstractmethod
    def inv(self, a):
        """Matrix inverse."""
        pass
    
    @abstractmethod
    def det(self, a):
        """Matrix determinant."""
        pass
    
    @abstractmethod
    def svd(self, a, full_matrices=True) -> Tuple:
        """Singular value decomposition."""
        pass
    
    @abstractmethod
    def norm(self, a, ord=None, axis=None):
        """Vector/matrix norm."""
        pass
    
    @abstractmethod
    def cross(self, a, b, axis=-1):
        """Cross product."""
        pass
    
    @abstractmethod
    def dot(self, a, b):
        """Dot product."""
        pass
    
    # Element-wise operations
    @abstractmethod
    def exp(self, a):
        """Element-wise exponential."""
        pass
    
    @abstractmethod
    def sin(self, a):
        """Element-wise sine."""
        pass
    
    @abstractmethod
    def cos(self, a):
        """Element-wise cosine."""
        pass
    
    @abstractmethod
    def sqrt(self, a):
        """Element-wise square root."""
        pass
    
    @abstractmethod
    def conj(self, a):
        """Complex conjugate."""
        pass
    
    @abstractmethod
    def real(self, a):
        """Real part."""
        pass
    
    @abstractmethod
    def imag(self, a):
        """Imaginary part."""
        pass
    
    @abstractmethod
    def abs(self, a):
        """Absolute value."""
        pass
    
    # Reduction operations
    @abstractmethod
    def sum(self, a, axis=None, keepdims=False):
        """Sum reduction."""
        pass
    
    @abstractmethod
    def mean(self, a, axis=None, keepdims=False):
        """Mean reduction."""
        pass
    
    @abstractmethod
    def max(self, a, axis=None, keepdims=False):
        """Max reduction."""
        pass
    
    @abstractmethod
    def min(self, a, axis=None, keepdims=False):
        """Min reduction."""
        pass
    
    # Bogoliubov diagonalization (key for spin wave theory)
    @abstractmethod
    def bogoliubov_diagonalize(self, H, n_modes: int) -> Tuple:
        """
        Diagonalize a bosonic Bogoliubov Hamiltonian.
        
        For spin wave calculations, the Hamiltonian has the form:
        H = [A, B; B*, A*] where A is Hermitian.
        
        Returns eigenvalues and transformation matrix.
        """
        pass
    
    # Colpa diagonalization for para-unitary matrices
    @abstractmethod
    def colpa_diagonalize(self, H, n_modes: int) -> Tuple:
        """
        Colpa's method for diagonalizing para-Hermitian matrices.
        
        This is the standard method for linear spin wave theory
        when the Hamiltonian is not positive definite.
        
        Reference: J.H.P. Colpa, Physica 93A (1978) 327
        
        Parameters
        ----------
        H : array
            The Hamiltonian matrix of shape (2n, 2n) in the form [[A, B], [B*, A*]]
        n_modes : int
            Number of magnon modes (n)
            
        Returns
        -------
        omega : array
            Eigenvalues (spin wave energies)
        T : array
            Transformation matrix
        """
        pass


class BackendError(Exception):
    """Exception for backend-related errors."""
    pass
