import enum
import sys
from typing import List, Tuple
from datetime import timedelta
from urllib.parse import urlparse

# Managed Role privileges


class PrivilegeScope(enum.IntEnum):
    All = 1,
    MSP = 2,
    Hidden = 3,


ROLE_PRIVILEGES = [
    ('Manage Nodes', 'MANAGE_NODES', PrivilegeScope.All),
    ('Manage Users', 'MANAGE_USER', PrivilegeScope.All),
    ('Manage Licences', 'MANAGE_LICENCES', PrivilegeScope.Hidden),
    ('Manage Roles', 'MANAGE_ROLES', PrivilegeScope.All),
    ('Manage Teams', 'MANAGE_TEAMS', PrivilegeScope.All),
    ('Run Security Reports', 'RUN_REPORTS', PrivilegeScope.All),
    ('Manage Bridge/SSO', 'MANAGE_BRIDGE', PrivilegeScope.All),
    ('Perform Device Approvals', 'APPROVE_DEVICE', PrivilegeScope.All),
    ('Manage Record Types in Vault', 'MANAGE_RECORD_TYPES', PrivilegeScope.All),
    ('Run Compliance Reports', 'RUN_COMPLIANCE_REPORTS', PrivilegeScope.All),
    ('Manage Companies', 'MANAGE_COMPANIES', PrivilegeScope.MSP),
    ('Transfer Account', 'TRANSFER_ACCOUNT', PrivilegeScope.All),
    ('Sharing Administrator', 'SHARING_ADMINISTRATOR', PrivilegeScope.All),
]

# Timeout constants
# Set to default value by using timedelta of 0
TIMEOUT_DEFAULT = timedelta(0)
TIMEOUT_MIN = timedelta(minutes=1)
TIMEOUT_DEFAULT_UNIT = 'minutes'
TIMEOUT_ALLOWED_UNITS = ('days', 'hours', 'minutes')

EMAIL_PATTERN = r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)"

# Enforcement constants

_ENFORCEMENT_GROUPS = [
    "LOGIN_SETTINGS",
    "TWO_FACTOR_AUTHENTICATION",
    "PLATFORM_RESTRICTION",
    "VAULT_FEATURES",
    "RECORD_TYPES",
    "SHARING_AND_UPLOADING",
    "KEEPER_FILL",
    "ACCOUNT_SETTINGS",
    "ALLOW_IP_LIST",
    "ACCOUNT_SETTINGS",
]

_ENFORCEMENTS = [
    ("MASTER_PASSWORD_MINIMUM_LENGTH", 10, "LONG", "LOGIN_SETTINGS"),
    ("MASTER_PASSWORD_MINIMUM_SPECIAL", 11, "LONG", "LOGIN_SETTINGS"),
    ("MASTER_PASSWORD_MINIMUM_UPPER", 12, "LONG", "LOGIN_SETTINGS"),
    ("MASTER_PASSWORD_MINIMUM_LOWER", 13, "LONG", "LOGIN_SETTINGS"),
    ("MASTER_PASSWORD_MINIMUM_DIGITS", 14, "LONG", "LOGIN_SETTINGS"),
    ("MASTER_PASSWORD_RESTRICT_DAYS_BEFORE_REUSE", 16, "LONG", "LOGIN_SETTINGS"),
    ("REQUIRE_TWO_FACTOR", 20, "BOOLEAN", "TWO_FACTOR_AUTHENTICATION"),
    ("MASTER_PASSWORD_MAXIMUM_DAYS_BEFORE_CHANGE", 22, "LONG", "LOGIN_SETTINGS"),
    ("MASTER_PASSWORD_EXPIRED_AS_OF", 23, "LONG", "LOGIN_SETTINGS"),
    ("MINIMUM_PBKDF2_ITERATIONS", 55, "LONG", "ACCOUNT_SETTINGS"),
    ("MAX_SESSION_LOGIN_TIME", 24, "LONG", "ACCOUNT_SETTINGS"),
    ("RESTRICT_PERSISTENT_LOGIN", 25, "BOOLEAN", "ACCOUNT_SETTINGS"),
    ("STAY_LOGGED_IN_DEFAULT", 26, "BOOLEAN", "ACCOUNT_ENFORCEMENTS"),
    ("RESTRICT_SHARING_ALL", 30, "BOOLEAN", "SHARING_AND_UPLOADING"),
    ("RESTRICT_SHARING_ENTERPRISE", 31, "BOOLEAN", "SHARING_AND_UPLOADING"),
    ("RESTRICT_EXPORT", 32, "BOOLEAN", "SHARING_AND_UPLOADING"),
    ("RESTRICT_IMPORT", 111, "BOOLEAN", "SHARING_AND_UPLOADING"),
    ("RESTRICT_FILE_UPLOAD", 33, "BOOLEAN", "SHARING_AND_UPLOADING"),
    ("REQUIRE_ACCOUNT_SHARE", 34, "ACCOUNT_SHARE"),
    ("RESTRICT_SHARING_INCOMING_ALL", 36, "BOOLEAN", "SHARING_AND_UPLOADING"),
    ("RESTRICT_SHARING_INCOMING_ENTERPRISE", 37, "BOOLEAN", "SHARING_AND_UPLOADING"),
    ("RESTIRCT_SHARING_RECORD_AND_FOLDER", 120, "BOOLEAN", "SHARING_AND_UPLOADING"),
    ("RESTRICT_SHARING_RECORD_WITH_ATTACHMENTS", 121, "BOOLEAN", "SHARING_AND_UPLOADING"),
    ("RESTRICT_IP_ADDRESSES", 40, "IP_WHITELIST", "ALLOW_IP_LIST"),
    ("REQUIRE_DEVICE_APPROVAL", 41, "BOOLEAN", "ACCOUNT_SETTINGS"),
    ("REQUIRE_ACCOUNT_RECOVERY_APPROVAL", 42, "BOOLEAN", "ACCOUNT_SETTINGS"),
    ("RESTRICT_VAULT_IP_ADDRESSES", 43, "IP_WHITELIST", "ALLOW_IP_LIST"),
    ("TIP_ZONE_RESTRICT_ALLOWED_IP_RANGES", 44, "IP_WHITELIST", "ALLOW_IP_LIST"),
    ("AUTOMATIC_BACKUP_EVERY_X_DAYS", 45, "LONG", "ACCOUNT_SETTINGS"),
    ("RESTRICT_OFFLINE_ACCESS", 46, "BOOLEAN", "ACCOUNT_SETTINGS"),
    ("SEND_INVITE_AT_REGISTRATION", 47, "BOOLEAN", "ACCOUNT_SETTINGS"),
    ("RESTRICT_EMAIL_CHANGE", 48, "BOOLEAN", "ACCOUNT_SETTINGS"),
    ("RESTRICT_IOS_FINGERPRINT", 49, "BOOLEAN", "LOGIN_SETTINGS"),
    ("RESTRICT_MAC_FINGERPRINT", 50, "BOOLEAN", "LOGIN_SETTINGS"),
    ("RESTRICT_ANDROID_FINGERPRINT", 51, "BOOLEAN", "LOGIN_SETTINGS"),
    ("RESTRICT_WINDOWS_FINGERPRINT", 83, "BOOLEAN", "LOGIN_SETTINGS"),
    ("LOGOUT_TIMER_WEB", 52, "LONG", "ACCOUNT_SETTINGS"),
    ("LOGOUT_TIMER_MOBILE", 53, "LONG", "ACCOUNT_SETTINGS"),
    ("LOGOUT_TIMER_DESKTOP", 54, "LONG", "ACCOUNT_SETTINGS"),
    ("RESTRICT_WEB_VAULT_ACCESS", 60, "BOOLEAN", "PLATFORM_RESTRICTION"),
    ("RESTRICT_EXTENSIONS_ACCESS", 61, "BOOLEAN", "PLATFORM_RESTRICTION"),
    ("RESTRICT_MOBILE_ACCESS", 62, " BOOLEAN", "PLATFORM_RESTRICTION"),
    ("RESTRICT_DESKTOP_ACCESS", 63, "BOOLEAN", "PLATFORM_RESTRICTION"),
    ("RESTRICT_MOBILE_IOS_ACCESS", 64, "BOOLEAN", "PLATFORM_RESTRICTION"),
    ("RESTRICT_MOBILE_ANDROID_ACCESS", 65, "BOOLEAN", "PLATFORM_RESTRICTION"),
    ("RESTRICT_MOBILE_WINDOWS_PHONE_ACCESS", 66, "BOOLEAN", "PLATFORM_RESTRICTION"),
    ("RESTRICT_DESKTOP_WIN_ACCESS", 67, "BOOLEAN", "PLATFORM_RESTRICTION"),
    ("RESTRICT_DESKTOP_MAC_ACCESS", 68, "BOOLEAN", "PLATFORM_RESTRICTION"),
    ("RESTRICT_CHAT_DESKTOP_ACCESS", 84, "BOOLEAN", "PLATFORM_RESTRICTION"),
    ("RESTRICT_CHAT_MOBILE_ACCESS", 85, "BOOLEAN", "PLATFORM_RESTRICTION"),
    ("RESTRICT_COMMANDER_ACCESS", 88, "BOOLEAN", "PLATFORM_RESTRICTION"),
    ("RESTRICT_TWO_FACTOR_CHANNEL_TEXT", 70, "BOOLEAN", "TWO_FACTOR_AUTHENTICATION"),
    ("RESTRICT_TWO_FACTOR_CHANNEL_GOOGLE", 71, "BOOLEAN", "TWO_FACTOR_AUTHENTICATION"),
    ("RESTRICT_TWO_FACTOR_CHANNEL_DNA", 72, "BOOLEAN", "TWO_FACTOR_AUTHENTICATION"),
    ("RESTRICT_TWO_FACTOR_CHANNEL_DUO", 73, "BOOLEAN", "TWO_FACTOR_AUTHENTICATION"),
    ("RESTRICT_TWO_FACTOR_CHANNEL_RSA", 74, "BOOLEAN", "TWO_FACTOR_AUTHENTICATION"),
    ("TWO_FACTOR_DURATION_WEB", 80, "TWO_FACTOR_DURATION", "TWO_FACTOR_AUTHENTICATION"),
    ("TWO_FACTOR_DURATION_MOBILE", 81, "TWO_FACTOR_DURATION", "TWO_FACTOR_AUTHENTICATION"),
    ("TWO_FACTOR_DURATION_DESKTOP", 82, "TWO_FACTOR_DURATION", "TWO_FACTOR_AUTHENTICATION"),
    ("RESTRICT_TWO_FACTOR_CHANNEL_SECURITY_KEYS", 86, "BOOLEAN", "TWO_FACTOR_AUTHENTICATION"),
    ("TWO_FACTOR_BY_IP", 87, "JSONARRAY"),
    ("RESTRICT_DOMAIN_ACCESS", 90, "STRING", "KEEPER_FILL"),
    ("RESTRICT_DOMAIN_CREATE", 91, "STRING", "KEEPER_FILL"),
    ("RESTRICT_HOVER_LOCKS", 92, "BOOLEAN", "KEEPER_FILL"),
    ("RESTRICT_PROMPT_TO_LOGIN", 93, "BOOLEAN", "KEEPER_FILL"),
    ("RESTRICT_PROMPT_TO_FILL", 94, "BOOLEAN", "KEEPER_FILL"),
    ("RESTRICT_AUTO_SUBMIT", 95, "BOOLEAN", "KEEPER_FILL"),
    ("RESTRICT_PROMPT_TO_SAVE", 96, "BOOLEAN", "KEEPER_FILL"),
    ("RESTRICT_PROMPT_TO_CHANGE", 97, "BOOLEAN", "KEEPER_FILL"),
    ("RESTRICT_AUTO_FILL", 98, "BOOLEAN", "KEEPER_FILL"),
    ("RESTRICT_CREATE_FOLDER", 100, "BOOLEAN", "VAULT_FEATURES"),
    ("RESTRICT_CREATE_IDENTITY_PAYMENT_RECORDS", 102, "BOOLEAN", "VAULT_FEATURES"),
    ("MASK_CUSTOM_FIELDS", 103, "BOOLEAN", "VAULT_FEATURES"),
    ("MASK_NOTES", 104, "BOOLEAN", "VAULT_FEATURES"),
    ("MASK_PASSWORDS_WHILE_EDITING", 105, "BOOLEAN", "VAULT_FEATURES"),
    ("GENERATED_PASSWORD_COMPLEXITY", 106, "STRING", "VAULT_FEATURES"),
    ("GENERATED_SECURITY_QUESTION_COMPLEXITY", 109, "STRING", "VAULT_FEATURES"),
    ("DAYS_BEFORE_DELETED_RECORDS_CLEARED_PERM", 107, "LONG", "VAULT_FEATURES"),
    ("DAYS_BEFORE_DELETED_RECORDS_AUTO_CLEARED", 108, "LONG", "VAULT_FEATURES"),
    ("ALLOW_ALTERNATE_PASSWORDS", 110, "BOOLEAN", "LOGIN_SETTINGS"),
    ("RESTRICT_LINK_SHARING", 122, "BOOLEAN", "SHARING_ENFORCEMENTS"),
    ("DISABLE_SETUP_TOUR", 140, "BOOLEAN", "VAULT_FEATURES"),
    ("RESTRICT_PERSONAL_LICENSE", 141, "BOOLEAN", "ACCOUNT_SETTINGS"),
    ("DISABLE_ONBOARDING", 142, "BOOLEAN", "ACCOUNT_SETTINGS"),
    ("DISALLOW_V2_CLIENTS", 143, "BOOLEAN", "ACCOUNT_SETTINGS"),
    ("RESTRICT_IP_AUTOAPPROVAL", 144, "BOOLEAN", "ACCOUNT_SETTINGS"),
    ("SEND_BREACH_WATCH_EVENTS", 200, "BOOLEAN", "VAULT_FEATURES"),
    ("RESTRICT_BREACH_WATCH", 201, "BOOLEAN", "VAULT_FEATURES"),
    ("RESEND_ENTERPRISE_INVITE_IN_X_DAYS", 202, "LONG", "ACCOUNT_SETTINGS"),
    ("MASTER_PASSWORD_REENTRY", 203, "JSON"),
    ("RESTRICT_ACCOUNT_RECOVERY", 204, "BOOLEAN", "ACCOUNT_SETTINGS"),
    ("KEEPER_FILL_HOVER_LOCKS", 205, "TERNARY_DEN", "KEEPER_FILL"),
    ("KEEPER_FILL_AUTO_FILL", 206, "TERNARY_DEN", "KEEPER_FILL"),
    ("KEEPER_FILL_AUTO_SUBMIT", 207, "TERNARY_DEN", "KEEPER_FILL"),
    ("KEEPER_FILL_MATCH_ON_SUBDOMAIN", 208, "TERNARY_EDN", "KEEPER_FILL"),
    ("RESTRICT_PROMPT_TO_DISABLE", 209, "BOOLEAN", "KEEPER_FILL"),
    ("RESTRICT_HTTP_FILL_WARNING", 210, "BOOLEAN", "KEEPER_FILL"),
    ("RESTRICT_RECORD_TYPES", 211, "RECORD_TYPES", "RECORD_TYPES"),
    ("ALLOW_SECRETS_MANAGER", 212, "BOOLEAN", "VAULT_FEATURES"),
    ("REQUIRE_SELF_DESTRUCT", 213, "BOOLEAN", "ACCOUNT_ENFORCEMENTS"),
]


def enforcement_list():  # type: () -> List[Tuple[str, str, str]]
    groups = {x[1]: x[0] for x in enumerate(_ENFORCEMENT_GROUPS)}
    enforcements = [(x[3], x[0], x[1], x[2]) for x in _ENFORCEMENTS if len(x) >= 4 and x[3]]
    enforcements.sort(key=lambda x: (groups[x[0]] if x[0] in groups else 100) * 1000 + x[2])
    return [(x[0].title().replace('_', ' '), x[1].lower(), x[3].lower()) for x in enforcements]


ENFORCEMENTS = {}
for e in _ENFORCEMENTS:
    ENFORCEMENTS[e[0].lower()] = e[2].lower()

# OS dependent constants
if sys.platform.startswith('win'):
    OS_WHICH_CMD = 'where'
else:
    OS_WHICH_CMD = 'which'


KEEPER_PUBLIC_HOSTS = {
    'US': 'keepersecurity.com',
    'EU': 'keepersecurity.eu',
    'AU': 'keepersecurity.com.au',
    'GOV': 'govcloud.keepersecurity.us'
}


def get_abbrev_by_host(host):
    # Return abbreviation of the Keeper's public host

    if host.startswith('https:'):
        host = urlparse(host).netloc    # https://keepersecurity.com/api/v2/ --> keepersecurity.com

    keys = [k for k, v in KEEPER_PUBLIC_HOSTS.items() if v == host]
    if keys:
        return keys[0]
    return None

# Messages
# Account Transfer
ACCOUNT_TRANSFER_MSG = """
Your Keeper administrator has enabled the ability to transfer your vault records
in accordance with company operating procedures and policies.
Please acknowledge this change in account settings by typing 'Accept'.
If you do not accept this change by {0}, you will be locked out of your account.
"""
