from typing import Any
import re


def get_MD(tag_bytes: bytes,
           no_tag: Any = None) -> str:
    """Extract the MD tag from a raw BAM alignment bytestring

    Parameters
    ----------
        tag_bytes : bytes
            a bytestring containing bam formatted tag elements

        no_tag : Any
            return value for when tag not found (default: None)

    Returns
    -------
        MD Tag Value : str
            an ASCII string representing the SAM format value of the MD tag
            returns the value of no_tag if tag absent (default: None)

    Raises
    ------
        ValueError
            raises a ValueError if more than one tag match

    Notes
    -----
    The MD field aims to achieve SNP/indel calling independent of the reference.
    Numbers represent matches, letters bases that differ from the reference and
    bases preceeded by ^ are deletions. A ^T0A indicates a base change to an A
    immediately following a deleted T.

    Recommended try accept for use on raw alignment with fall back
    to calling on only the tag byte string.

    Please test carefully on your BAM output as in complicated output the
    regular expression based extraction of the tag can be error prone

    """
    match = re.findall(b"MDZ[0-9ACGTN^]+\x00", tag_bytes)
    if not match:
        return no_tag
    elif len(match) != 1:
        raise ValueError(
            (f"More than one match to b'MDZ[0-9ACGTN^]+\x00' was found in "
             f"{tag_bytes} "
             "meaning that more than one value of the tag is present"
             "or that another tag contains a match as part of its value")
        )
    else:
        return match[0][3:-1].decode()