# Match the identifiers org prefix as group 1, and the actual id as group 2
import re
from typing import Optional

from chemrecon.core.id_types import (IdentifierType, IdentifierTypeAAM, IdentifierTypeCompound,
                           IdentifierTypeEnzyme, IdentifierTypeReaction,
                           IdentifierTypeStructureRepresentation,
                           id_types_aam, id_types_compound,
                           id_types_enzyme, id_types_reaction, id_types_structure_representation,
                           identifiers_org_dict, )

identifiers_org_regex = re.compile(r'(https?://identifiers.org/[a-zA-Z./\-]+/)(.+)')

# Sub-lookup dicts for identifier type names for each entrytype (compounds, reactions, etc)
id_type_name_lookup_subsdicts: dict[type[IdentifierType], dict[str, IdentifierType]] = dict()
typelists: dict[type[IdentifierType], list[IdentifierType]] = {
    IdentifierTypeCompound: id_types_compound,
    IdentifierTypeStructureRepresentation: id_types_structure_representation,
    IdentifierTypeReaction: id_types_reaction,
    IdentifierTypeEnzyme: id_types_enzyme,
    IdentifierTypeAAM: id_types_aam
}
for entrytype_idtype, idtypes in typelists.items():
    subdict: dict[str, IdentifierType] = dict()
    for idtype in idtypes:
        subdict[idtype.name.lower()] = idtype
        subdict[idtype.shortname.lower()] = idtype
        for name in idtype.alt_names:
            subdict[name.lower()] = idtype
    id_type_name_lookup_subsdicts[entrytype_idtype] = subdict



def get_id_type[T: IdentifierType](
    type_str: str,
    identifier_supertype: type[T]
) -> Optional[T]:
    """ Get an identifier type by a strign description. """
    try:
        return id_type_name_lookup_subsdicts[identifier_supertype][type_str.lower()]
    except KeyError:
        return None

def get_id_type_from_name[T: IdentifierType](name: str) -> T:
    """ Get an identifier type (of type T, e.g. Compound, Reaction, Struct representation, ...) """
    raise NotImplementedError

def get_possible_id_types_from_source_id[T: IdentifierType](name: str) -> list[T]:
    """ Get a list of possible compatible identifiers (of type T, e.g. Compound, Reaction,
    Struct representation, ...) """
    raise NotImplementedError

def get_id_from_identifiers_org(
    string: str,
    identifier_supertype: type[IdentifierType]
) -> Optional[tuple[IdentifierType, str]]:
    """ Get an identifier type (of type T, e.g. Compound, Reaction, Struct representation, ...) """
    match = re.match(identifiers_org_regex, string)
    if match:
        prefix = match.group(1)
        match_id = match.group(2).removesuffix('/')     # TODO should trailing '/' be removed in all cases?
        try:
            id_type: IdentifierType = identifiers_org_dict[prefix]
            if not isinstance(id_type, identifier_supertype):
                return None
            return (id_type, match_id)
        except KeyError:
            return None
    else:
        return None
