import string
import re
from moto.moto_api._internal import mock_random as random


def random_password(
    password_length,
    exclude_characters,
    exclude_numbers,
    exclude_punctuation,
    exclude_uppercase,
    exclude_lowercase,
    include_space,
    require_each_included_type,
):

    password = ""
    required_characters = ""

    if not exclude_lowercase and not exclude_uppercase:
        password += string.ascii_letters
        required_characters += random.choice(
            _exclude_characters(string.ascii_lowercase, exclude_characters)
        )
        required_characters += random.choice(
            _exclude_characters(string.ascii_uppercase, exclude_characters)
        )
    elif not exclude_lowercase:
        password += string.ascii_lowercase
        required_characters += random.choice(
            _exclude_characters(string.ascii_lowercase, exclude_characters)
        )
    elif not exclude_uppercase:
        password += string.ascii_uppercase
        required_characters += random.choice(
            _exclude_characters(string.ascii_uppercase, exclude_characters)
        )
    if not exclude_numbers:
        password += string.digits
        required_characters += random.choice(
            _exclude_characters(string.digits, exclude_characters)
        )
    if not exclude_punctuation:
        password += string.punctuation
        required_characters += random.choice(
            _exclude_characters(string.punctuation, exclude_characters)
        )
    if include_space:
        password += " "
        required_characters += " "
    if exclude_characters:
        password = _exclude_characters(password, exclude_characters)

    password = "".join(str(random.choice(password)) for x in range(password_length))

    if require_each_included_type:
        password = _add_password_require_each_included_type(
            password, required_characters
        )

    return password


def secret_arn(account_id, region, secret_id):
    id_string = "".join(random.choice(string.ascii_letters) for _ in range(6))
    return (
        f"arn:aws:secretsmanager:{region}:{account_id}:secret:{secret_id}-{id_string}"
    )


def get_secret_name_from_arn(secret_id):
    # can fetch by both arn and by name
    # but we are storing via name
    # so we need to change the arn to name
    # if it starts with arn then the secret id is arn
    if secret_id.startswith("arn:aws:secretsmanager:"):
        # split the arn by colon
        # then get the last value which is the name appended with a random string
        # then remove the random string
        secret_id = "-".join(secret_id.split(":")[-1].split("-")[:-1])
    return secret_id


def _exclude_characters(password, exclude_characters):
    for c in exclude_characters:
        if c in string.punctuation:
            # Escape punctuation regex usage
            c = rf"\{c}"
        password = re.sub(c, "", str(password))
    return password


def _add_password_require_each_included_type(password, required_characters):
    password_with_required_char = password[: -len(required_characters)]
    password_with_required_char += required_characters

    return password_with_required_char
