import numpy                as    np
import sympy                as    sp
from   sympy                import latex
from   IPython.display      import Math, display

def display_matrix(matrix, name="Matrix", r=8, c=8, evalf=False, prec=5, mathrm=True):
    """
    Displays a truncated matrix with optional numerical evaluation and rational simplification.
    
    Parameters:
        matrix  : Input matrix (NumPy array, SymPy Matrix, or list)
        name    : Display name (default: "Matrix")
        r       : Max rows to display (default: 8)
        c       : Max columns to display (default: 8)
        evalf   : If True, apply numerical evaluation (default: False)
        prec    : Evaluate the given formula to an accuracy of prec digits
        mathrm  : Boolean to display as Roman text (default: True)

    Returns:
        None
    """

    # Safe Rounding Helper
    def _safe_round(x):
        try:
            x = sp.sympify(x)
            return x.replace(
                lambda a: isinstance(a, sp.Float),
                lambda a: sp.Float(round(float(a), prec))
            ).evalf(prec)
        except (TypeError, ValueError):
            return x

    # Matrix Preparation
    def _prepare_matrix(raw_mat):
        if isinstance(raw_mat, (np.ndarray, list)):
            return sp.Matrix(raw_mat)
        return raw_mat

    # Processing (Truncation & Evaluation)
    def _process_submatrix(full_mat):
        # Truncate
        sub = full_mat[:min(r, full_mat.rows), :min(c, full_mat.cols)]
        
        # Evaluate
        if evalf:
            return sub.applyfunc(_safe_round)
        return sub

    # Rendering
    def _render(processed_sub, original_rows, original_cols):
        # Generate LaTeX with spacing adjustment
        expr = latex(processed_sub).replace(r'\\', r'\\[5pt]')
        
        if mathrm:
            expr = rf"\mathrm{{{expr}}}"
        
        # Display Main Equation
        label = rf"\large {name} =" if name else r"\large"
        display(Math(rf"{label} {expr}"))

        # Display Truncation Message
        if original_rows > r or original_cols > c:
            msg = rf"\text{{... Truncated to first {r}x{c} out of {original_rows}x{original_cols} matrix}}"
            display(Math(msg))

    # Main Execution
    sym_matrix = _prepare_matrix(matrix)
    sub_matrix = _process_submatrix(sym_matrix)
    _render(sub_matrix, sym_matrix.rows, sym_matrix.cols)