#!/usr/bin/env python
# -*- coding: utf8 -*-

description = """

Токены создавать на страницах
https://sentry-test.t.yandex-team.ru/settings/account/api/auth-tokens/
https://sentry.t.yandex-team.ru/settings/account/api/auth-tokens/
и класть в файлы
~/.sentry-auth-token-test
~/.sentry-auth-token-prod

dt-sentry-cli --org direct --test members invite larilena
dt-sentry-cli --org direct --test members list
dt-sentry-cli --org direct --test members reinvite dspushkin@yandex-team.ru

"""

TODO = """
"""


import os
import re
import sys

sys.path.insert(0, '/opt/direct-py/startrek-python-client-sni-fix')

import argparse
import copy
import fnmatch
import hashlib
import json
import requests
import shutil
import socket
import subprocess
import tempfile
import time
import urllib
from collections import defaultdict

from requests.packages.urllib3.exceptions import InsecureRequestWarning
# чтобы не было ворнингов при обращении к tabula/yamb_send
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

SENTRY_TYPE = None
SENTRY_ORG  = None
token = None

def init_cmds():
    global cmds
    cmds = {
            "members": {
                'invite': {
                    'code': cmd_invite,
                    'desc': 'Пригласить пользователя, по логину',
                    },
                'reinvite': {
                    'code': cmd_reinvite,
                    'desc': 'Повторно отослать приглашение на почту, по email-у',
                    },
                'list': {
                    'code': cmd_members_list,
                    'desc': 'Список участников',
                    },
                }
            }

#######
# Вспомогательные ф-ции
def die(message=''):
    sys.stderr.write("%s\n" % message)
    exit(1)

def my_system(cmd, verbose=False):
    if verbose:
        print("going to exec: %s\n" % cmd)
    exit_code = subprocess.call(cmd)
    if exit_code != 0:
        die("cmd failed, stop (%s)" % cmd)
    return
#######

#######
# 
def get_members():
    # curl -X GET -H 'Content-Type: application/json' -H 'Authorization: Bearer ...' https://sentry-test.t.yandex-team.ru/api/0/organizations/direct/members/
    members = []
    url = sentry_url('members')
    done = False
    while (not done):
        r = requests.get(url, headers = get_headers(), verify=False)
        #print r.headers['Link']
        links = requests.utils.parse_header_links(r.headers['Link'])
        done = True
        #{'url': 'https://sentry-test.t.yandex-team.ru/api/0/organizations/direct/members/?&cursor=100:1:0', 'cursor': '100:1:0', 'results': 'false', 'rel': 'next'}
        # смотрим, надо ли будет читать следующую страницу результатов
        for l in links:
            if l['rel'] == 'next' and l['results'] == 'true':
                done = False
                url = l['url']
        members_chunk = r.json()
        members += members_chunk
    return members

def get_member_by_email(email):
    members = get_members()
    for m in members:
        if m['email'] == email:
            return m 
    return None

#######
# Обработка команд

def cmd_invite(extra):
    if len(extra) != 1:
        die("expecting 1 parameter, %s found" % (len(extra)))
    login     = extra[0]

    # curl -X POST -H 'Content-Type: application/json' -H 'Authorization: Bearer ...' -d '{"email":"larilena@yandex-team.ru","role":"member","teams":["backend"]}' https://sentry-test.t.yandex-team.ru/api/0/organizations/direct/members/
    url = sentry_url('members')
    data = {
            "email": "%s@yandex-team.ru" % (login),
            "role": "member",
            "teams": ["backend"],
            }
    r = requests.post(url, data = json.dumps(data), headers = get_headers(), verify=False, timeout = 10)
    if r.status_code != 201:
        print "status: %s\ncontent: %s" % (r.status_code, r.content)
        exit(1)

    res = r.json()
    new_id = res['id']
    print "id: %s" % new_id 
    
    #curl -X PUT -H 'Content-Type: application/json' -H 'Authorization: Bearer ...' -d '{"reinvite":1}' https://sentry-test.t.yandex-team.ru/api/0/organizations/direct/members/812/
    url = sentry_url('members') + '/%s/' % new_id
    data = {
            "reinvite": 1
            }
    r = requests.put(url, data = json.dumps(data),headers = get_headers(), verify=False)
    print "status: %s" % r.status_code

    return

def cmd_reinvite(extra):
    if len(extra) != 1:
        die("expecting 1 parameter, %s found" % (len(extra)))
    email     = extra[0]
    m = get_member_by_email(email)
    if m is None:
        die("can't find any user with email '%s'" % email)
    print m['id']
    url = sentry_url('members') + '/%s/' % m['id']
    data = {
            "reinvite": 1
            }
    r = requests.put(url, data = json.dumps(data), headers = get_headers(), verify=False)
    print "status: %s" % r.status_code

    return


def cmd_members_list(extra):
    members = get_members()
    for m in members:
        '''
        в m лежит такое:
        {
            'name': 'Igor Gerdler',
                'dateCreated': '2018-11-13T10:01:57.234Z',
                'email': 'gerdler@yandex-team.r',
                'flags': {'sso:linked': False,
                    'sso:invalid': False},
                'user': {'username': 'gerdler@yandex-team.r',
                    'name': 'Igor Gerdler',
                    'avatarUrl': 'https://center.yandex-team.ru/avatar/c8be0218212b11ecf615ba4cb8afd31f?s=32&d=mm',
                    'hasPasswordAuth': True,
                    'dateJoined': '2018-11-13T10:25:59.685Z',
                    'emails': [{'is_verified': True,
                        'id': '497',
                        'email': 'gerdler@yandex-team.r'}],
                    'email': 'gerdler@yandex-team.r',
                    'isManaged': False,
                    'lastActive': '2018-11-13T10:36:12.967Z',
                    'avatar': {'avatarUuid': None,
                        'avatarType': 'letter_avatar'},
                    'lastLogin': '2018-11-13T10:26:00.255Z',
                    'id': '357',
                    'isActive': True,
                    'has2fa': False},
                'roleName': 'Manager',
                'role': 'manager',
                'id': '597',
                'pending': False
        }
        '''

        status = 'pending' if m['pending'] else 'active'
        
        if m['user'] is not None and m['user']['username'] is not None:
            username = m['user']['username']
        elif m['email'] is not None:
            username = m['email']
        else:
            username = "???"

        data = [ m['id'], m['role'], status, username ]
        print "\t".join(data)

    return


######
# вспомогательное
def get_headers(content_type=True):
    global token

    headers = { 
            "Authorization": "Bearer %s" % token,
            }
    if content_type:
        headers['Content-Type'] = 'application/json'
    return headers


######
# общий цикл 

def do_one_cmd(opts):

    # выполняем запрошенное действие
    cmds[opts.service][opts.cmd]['code'](opts.extra)

    return 0


def parse_options():
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument("-h", "--help", dest="help", help="Справка", action="store_true")
    parser.add_argument("--test", dest="sentry_type_test", help="Работать с тестовой Sentry", action="store_true")
    parser.add_argument("--prod", dest="sentry_type_prod", help="Работать с продакшеновой Sentry", action="store_true")
    parser.add_argument("-o", "--org", dest="sentry_org", help="Организация в Sentry", type=str)
    parser.add_argument("--sentry-token-file", dest="token_file", help="файл с токеном для Sentry", type=str)
    opts, extra = parser.parse_known_args()

    if opts.help:
        print description
        print parser.format_help()
        print "commands:"
        for service in sorted(cmds.keys()):
            for cmd in sorted(cmds[service].keys()):
                print "%s %s\n  %s" % (service, cmd, cmds[service][cmd]['desc'])
        exit(0)

    if not opts.sentry_org:
        die("expections organization (e.g. --org direct)")
    global SENTRY_ORG
    SENTRY_ORG = opts.sentry_org

    if opts.token_file and not os.path.exists(os.path.expanduser(opts.token_file)):
        print u"file '%s' doesn't exist, stop" % opts.token_file
        sys.exit(1)

    if len(extra) < 2:
        die("expecting service (like 'members') and action")

    opts.service = extra.pop(0)
    opts.cmd = extra.pop(0)
    
    if not opts.service in cmds:
        die("unknown service '%s'" % opts.service)
    if not opts.cmd in cmds[opts.service]:
        die("unknown action '%s' for service '%s'" % (opts.cmd, opts.service))

    opts.extra = extra

    global SENTRY_TYPE
    if       opts.sentry_type_test and     opts.sentry_type_prod:
        die("--test and --prod must not be used together")
    elif not opts.sentry_type_test and not opts.sentry_type_prod:
        die("--test or --prod must be specified")
    elif not opts.sentry_type_test and     opts.sentry_type_prod:
        SENTRY_TYPE = 'prod'
    elif     opts.sentry_type_test and not opts.sentry_type_prod:
        SENTRY_TYPE = 'test'
    else:
        die("")

    return opts


def get_sentry_type():
    global SENTRY_TYPE
    if SENTRY_TYPE is None:
        die("empty SENTRY_TYPE, stop")
    return SENTRY_TYPE

def get_sentry_base_url():
    t = get_sentry_type()
    if t == 'test':
        return 'https://sentry-test.t.yandex-team.ru'
    elif t == 'prod':
        return 'https://sentry.t.yandex-team.ru'
    else:
        die("unknown sentry instance '%s'" % SENTRY_TYPE)
    return

def sentry_url(method):
    global SENTRY_ORG
    urls = {
            'members': '/api/0/organizations/%s/members/',
            }

    if not method in urls:
        die("unknown method %s" % method)
    url = get_sentry_base_url() + (urls[method] % SENTRY_ORG)
    return url

def get_token(token_file=None):
    token_env_var = "SENTRY_AUTH_TOKEN"
    default_token_file = "~/.sentry-auth-token-%s" % get_sentry_type()
    if os.environ.get(token_env_var, ""):
        return os.environ[token_env_var]
    elif token_file:
        with open(os.path.expanduser(token_file), "r") as f:
            return f.read().strip()
    elif os.path.exists(os.path.expanduser(default_token_file)):
        with open(os.path.expanduser(default_token_file), "r") as f:
            return f.read().strip()
    else:
        print u"can't find auth token for sentry"
        sys.exit(1)


def run():
    global token

    init_cmds()
    opts = parse_options()
    token = get_token(opts.token_file)
    
    do_one_cmd(opts)
    exit(0)


if __name__ == '__main__':
    run();
