import re
from maps.wikimap.stat.tasks_payment.dictionaries.libs.users import normalize_yalogin


YANDEX_EMAIL_REGEXP = r'(?P<login>[\w.-]+)@(?P<domain>[\w.-]+)'
YANDEX_EMAIL_DOMAIN_REGEXP = r'ya(ndex)?(\.com|\.net)?\.[a-z]+'
NMAPS_ACCOUNT_TYPE = "nmaps_login"

DUMP_FIELDS = ['uid', 'login', 'accounts', 'department_group', 'name', 'official.quit_at', 'official.is_dismissed']
DEPARTMENT_URL_KEYS = {'department_group.url', 'department_group.ancestors.url'}


def _yalogin_from_email(email):
    match = re.fullmatch(YANDEX_EMAIL_REGEXP, email.lower())
    if match is None:
        raise ValueError('Yandex e-mail "{}" does not match regexp'.format(email))
    if re.fullmatch(YANDEX_EMAIL_DOMAIN_REGEXP, match['domain']) is None:
        raise ValueError('Unexpected domain "{}" in yandex e-mail "{}"'.format(email, match['domain']))
    return normalize_yalogin(match['login'])


def _get_nmaps_logins(accounts):
    for account in accounts:
        if account['type'] == NMAPS_ACCOUNT_TYPE and not account['private']:
            yield _yalogin_from_email(account['value'])


def _get_departments(department_group):
    result = {
        'primary_department': department_group['name'],
        'primary_department_url': department_group['url'],
        'departments': [department_group['name']],
        'departments_urls': [department_group['url']]
    }
    for dep in department_group['ancestors'][::-1]:
        result['departments'].append(dep['name'])
        result['departments_urls'].append(dep['url'])
    return result


def _quit_at(is_dismissed, quit_at):
    if not is_dismissed:
        return None
    return quit_at


def describe_person(record):
    '''
    Expected record content: {
        "name": {"last": {"ru": <last_name>}, "first": {"ru": <first_name>}},
        "uid": <uid_str>,
        "login": <login>,
        "accounts": [{"value": <account>, "type": <type>, "private": <is_flag>}],
        "department_group": {
            "name": <name>,
            "url": <url>,
            "ancestors": [{"name": <name>, "url": <url>}],
        },
        "official" : {
            "quit_at" : <quit_at>
        }
    }
    '''
    accounts = record.get('accounts', [])
    return {
        'last_name': record['name']['last']['ru'],
        'first_name': record['name']['first']['ru'],
        'uid': int(record['uid']),
        'login': record['login'],
        'nmaps_logins': list(_get_nmaps_logins(accounts)),
        'quit_at': _quit_at(record['official']['is_dismissed'], record['official']['quit_at']),
        **_get_departments(record['department_group'])
    }


def dump_persons(staff, departments):
    records = staff.find_all(
        'persons',
        query=' or '.join(
            '{} == "{}"'.format(key, dep)
            for key in DEPARTMENT_URL_KEYS
            for dep in departments
        ),
        fields=DUMP_FIELDS
    )
    return map(describe_person, records)
