from typing import Optional
import re


def _can_disambiguate_from_context(
    line: str, old_string: str, type_: str
) -> Optional[bool]:
    """
    Check whether we can disambiguate the public id given contextual information.

    For example:
    - whether the public id appears in a line of the form 'aea fetch ...' (we know it's an agent)
    - whether the public id appears in a line of the form 'aea add ...' (we know the component type)
    - whether the type appears in the same line where the public id occurs.

    :param line: the line
    :param old_string: the old string
    :param type_: the type of package
    :return: if True/False, the old string can/cannot be replaced. If None, we don't know.
    """
    match = re.search(
        fr"aea +add +(skill|protocol|connection|contract) +{old_string}", line
    )
    if match is not None:
        return match.group(1) == type_[:-1]
    if re.search(fr"aea +fetch +{old_string}", line) is not None:
        return type_ == "agents"
    match = re.search(
        "(skill|SKILL|"
        + "protocol|PROTOCOL|"
        + "connection|CONNECTION|"
        + "contract|CONTRACT|"
        + "agent|AGENT"
        + f")s?.*{old_string}",
        line,
    )
    if match is not None:
        return (match.group(1) + "s") == type_

    # for protocol specification id only:
    # - if the line contains 'protocol_specification_id: {old_public_id}' or
    # - if the line contains 'protocol_specification_id = PublicId.from_str("{old_public_id}")'
    # then DON'T replace it (we only bump protocol ids here).
    # otherwise, we don't know -> return None and ask to user.
    case_1 = f"protocol_specification_id: {old_string}"
    case_2 = rf'protocol_specification_id = PublicId.from_str([\'"]{old_string}[\'"])'
    if re.search(case_1, line) or re.search(case_2, line):
        return True
    return None