# -*- coding:utf-8 -*-

import asyncio
import re
import xmlrpc.client

from odoo_api.exceptions import APIException


def call_xmlrpc(url: str, method: str, *args):
    proxy = xmlrpc.client.ServerProxy(url)
    return getattr(proxy, method)(*args)


def get_additional_context():
    return {
        "active_test": False
    }


def sanitize_error_message(err: Exception) -> str:
    if hasattr(err, 'faultString'):
        error_message = err.faultString
    else:
        error_message = str(err)
    messages = re.findall(r'^\S.*(?=error|exception).*', error_message, re.IGNORECASE | re.M)
    if not messages:
        messages = [error_message]
    return '\n'.join(messages)


async def execute(model, func_name, args, kwargs, additional_context=False):
    try:
        uid = kwargs.pop('uid', '')
        password = kwargs.pop('password', '')
        host = kwargs.pop('host', '')
        db = kwargs.pop('db', '')
        url = '{}/xmlrpc/2/object'.format(host)
        # add context for customized behavior
        context = kwargs.pop('context', {})
        if additional_context:
            merged = get_additional_context()
            merged.update(context)
            context = merged
        kwargs.update(dict(context=context))
        loop = asyncio.get_running_loop()
        data = await loop.run_in_executor(
            None, lambda: call_xmlrpc(url, 'execute_kw', db, uid, password, model, func_name, args, kwargs)
        )
        return data
    except Exception as e:
        error_message = sanitize_error_message(e)
        raise APIException(message=error_message)


def sanitize_model(model):
    """Use hyphen character to make RESTful API endpoint"""
    model = model.replace('-', '.')
    if not re.match(r'^[a-z][a-z0-9_.]+$', model):
        raise APIException(message="Invalid model name: %s" % model)
    return model

