#!/usr/bin/env python3

import argparse
import json
import xml.etree.ElementTree as ET
from urllib import parse

from os import chdir
chdir('/usr/local/mgr5')

import sys
sys.path.insert(0, '/usr/local/mgr5/lib/python')

import billmgr.exception as exc
import billmgr.logger as logging
logging.init_logging('omvkontakte')
logger = logging.get_logger('omvkontakte')

import requests


class VK:
    def __init__(self):
        with open('/usr/local/mgr5/etc/oauth/vkontakte.json', 'r') as f:
            raw = json.load(f)
            self.client_id = raw['client_id']
            self.secret = raw['secret']


    def make_url(self, state, response_type, return_url):
        params = {
            'client_id': self.client_id,
            'scope': '4194304', # email | '272629760' = email phone_number
            'display': 'popup',
            'response_type': response_type,
            'redirect_uri': return_url,
            'state': state,
        }

        url = f'https://oauth.vk.ru/authorize?{parse.urlencode(params)}'

        logger.info("URL: '%s'", url)

        doc = ET.Element('doc')
        ET.SubElement(doc, 'url').text = url
        ET.dump(doc)


    def get_user_data(self, code, return_url):
        logger.info("Try get access token")
        r = requests.get('https://oauth.vk.ru/access_token', params={
            'v': '5.131',
            'client_id': self.client_id,
            'client_secret': self.secret,
            'redirect_uri': return_url,
            'code': code,
        })
        logger.info("access token: %s", r.text)

        access_token = r.json()
        if 'error' in  access_token:
            raise exc.XmlException("access_token", access_token['error'], access_token['error_description'])

        if 'email' not in access_token:
            raise exc.XmlException("access_token", 'missed', 'email')

        logger.info("Try get user data")
        r = requests.get('https://api.vk.ru/method/users.get', params={
            'v': '5.131',
            'user_id': access_token['user_id'],
            'access_token': access_token['access_token'],
        })
        logger.info("user data: %s", r.text)

        response = r.json()
        if 'error' in  response:
            raise exc.XmlException("user_data", response['error'], response['error_description'])

        user = response['response'][0]

        doc = ET.Element('doc')
        info = ET.SubElement(doc, 'userdata')
        ET.SubElement(info, 'id').text = str(user['id'])
        ET.SubElement(info, 'email').text = access_token['email']
        ET.SubElement(info, 'realname').text = f"{user['first_name']} {user['last_name']}"
        ET.SubElement(info, 'firstname').text = user['first_name']
        ET.SubElement(info, 'lastname').text = user['last_name']
        ET.dump(doc)


def get_args():
    parser = argparse.ArgumentParser(description='Oauth VK')
    parser.add_argument('--test', '-T', help='test function for checker', dest='test', action='store_true')
    parser.add_argument('--command', type=str, help='command name', dest='command')
    parser.add_argument('--state', type=str, help='state', dest='state')
    parser.add_argument('--code', type=str, help='auth code from VK', dest='code')
    parser.add_argument('--response_type', type=str, help='the name of param with auth code from VK', dest='response_type')
    parser.add_argument('--return_url', type=str, help='url for return after authorize in VK', dest='return_url')
    parser.add_argument('--from', type=str, help='from', dest='from')
    parser.add_argument('--ip', type=str, help='ip', dest='ip')
    parser.add_argument("--params", type=str, help="extra session params as JSON", dest="params", default="{}")
    args, _ = parser.parse_known_args()
    logger.info("Args: %s", args)
    return args


def process_command():
    args = get_args()

    try:
        if args.test:
            sys.stdout.write("(c) ISPsystem.com")
            sys.exit(0)

        vk = VK()
        if args.command == "make_url":
            vk.make_url(args.state, args.response_type, args.return_url)

        elif args.command == "get_user_data":
            vk.get_user_data(args.code, args.return_url)

        else:
            raise exc.XmlException("unknown command", "", args.command)

    except Exception as err:
        exc.log_backtrace()
        if isinstance(err, exc.XmlException):
            xml_err = err
        else:
            xml_err = exc.XmlException(err_type=args.command, err_value=str(err))

        logger.error('%s', str(xml_err))
        print(xml_err.as_xml())

        sys.exit(1)


if __name__ == "__main__":
    process_command()