# Path: src/ext.py
# class ApiError(RuntimeError):
#     def __init__(self, method, url, status, response_text):
#         self.method = method
#         self.url = url
#         self.status = status
#         self.body = response_text
# 
#     def __str__(self):
#         return f'{self.method} {self.url}, unexpected response {self.status}'
# 
# class ApiSession:
#     def __init__(self, root_url, settings: Settings):
#         self.settings = settings
#         self.root = root_url.rstrip('/') + '/'
# 
#     async def get(self, uri, *, allowed_statuses=(200,), **data) -> Response:
#         return await self._request('GET', uri, allowed_statuses=allowed_statuses, **data)
# 
#     async def delete(self, uri, *, allowed_statuses=(200,), **data) -> Response:
#         return await self._request('DELETE', uri, allowed_statuses=allowed_statuses, **data)
# 
#     async def post(self, uri, *, allowed_statuses=(200, 201), **data) -> Response:
#         return await self._request('POST', uri, allowed_statuses=allowed_statuses, **data)
# 
#     async def put(self, uri, *, allowed_statuses=(200, 201), **data) -> Response:
#         return await self._request('PUT', uri, allowed_statuses=allowed_statuses, **data)
# 
#     async def _request(self, method, uri, allowed_statuses=(200, 201), **data) -> Response:
#         method, url, data = self._modify_request(method, self.root + str(uri).lstrip('/'), data)
#         kwargs = {}
#         headers = data.pop('headers_', None)
#         if headers is not None:
#             kwargs['headers'] = headers
#         if timeout := data.pop('timeout_', None):
#             kwargs['timeout'] = timeout
#         r = await glove.http.request(method, url, json=data or None, **kwargs)
#         if isinstance(allowed_statuses, int):
#             allowed_statuses = (allowed_statuses,)
#         if allowed_statuses != '*' and r.status_code not in allowed_statuses:
#             data = {
#                 'request_real_url': str(r.request.url),
#                 'request_headers': dict(r.request.headers),
#                 'request_data': data,
#                 'response_headers': dict(r.headers),
#                 'response_content': lenient_json(r.text),
#             }
#             logger.warning(
#                 '%s unexpected response %s /%s -> %s',
#                 self.__class__.__name__,
#                 method,
#                 uri,
#                 r.status_code,
#                 extra={'data': data} if self.settings.verbose_http_errors else {},
#             )
#             raise ApiError(method, url, r.status_code, r.text)
#         else:
#             logger.debug('%s /%s -> %s', method, uri, r.status_code)
#             return r
# 
#     def _modify_request(self, method, url, data):
#         return method, url, data
# 
# Path: tests/test_user_display.py
# def modify_url(url, settings, company='foobar'):
#     args = dict(company=company, expires=round(datetime(2032, 1, 1).timestamp()))
#     body = '{company}:{expires}'.format(**args).encode()
#     args['signature'] = hmac.new(settings.user_auth_key, body, hashlib.sha256).hexdigest()
#     return str(url) + ('&' if '?' in str(url) else '?') + urlencode(args)


import base64
import pytest
from foxglove.db.helpers import SyncDb
from foxglove.test_server import DummyServer
from foxglove.testing import Client
from starlette.testclient import TestClient
from src.ext import ApiError, ApiSession
from tests.test_user_display import modify_url


def test_robots(cli: TestClient):
    r = cli.get('/robots.txt')
    assert r.status_code == 200
    assert 'User-agent: *' in r.text


def test_favicon(cli: TestClient):
    r = cli.get('/favicon.ico', allow_redirects=False)
    assert r.status_code == 200
    assert 'image' in r.headers['Content-Type']  # value can vary


def test_405(cli: TestClient):
    r = cli.post('/')
    assert r.status_code == 405, r.text


def test_create_subaccount_new_few_sent(cli: Client, sync_db: SyncDb, dummy_server: DummyServer):
    data = {'company_code': 'foobar'}
    r = cli.post('/create-subaccount/email-mandrill/', json=data, headers={'Authorization': 'testing-key'})
    assert r.status_code == 201, r.text
    assert r.json() == {'message': 'subaccount created'}
    assert dummy_server.log == ['POST /mandrill/subaccounts/add.json > 200']

    r = cli.post('/create-subaccount/email-mandrill/', json=data, headers={'Authorization': 'testing-key'})
    assert r.status_code == 200, r.text
    assert r.json() == {
        'message': 'subaccount already exists with only 42 emails sent, reuse of subaccount id permitted'

# Path: src/ext.py
# class ApiError(RuntimeError):
#     def __init__(self, method, url, status, response_text):
#         self.method = method
#         self.url = url
#         self.status = status
#         self.body = response_text
# 
#     def __str__(self):
#         return f'{self.method} {self.url}, unexpected response {self.status}'
# 
# class ApiSession:
#     def __init__(self, root_url, settings: Settings):
#         self.settings = settings
#         self.root = root_url.rstrip('/') + '/'
# 
#     async def get(self, uri, *, allowed_statuses=(200,), **data) -> Response:
#         return await self._request('GET', uri, allowed_statuses=allowed_statuses, **data)
# 
#     async def delete(self, uri, *, allowed_statuses=(200,), **data) -> Response:
#         return await self._request('DELETE', uri, allowed_statuses=allowed_statuses, **data)
# 
#     async def post(self, uri, *, allowed_statuses=(200, 201), **data) -> Response:
#         return await self._request('POST', uri, allowed_statuses=allowed_statuses, **data)
# 
#     async def put(self, uri, *, allowed_statuses=(200, 201), **data) -> Response:
#         return await self._request('PUT', uri, allowed_statuses=allowed_statuses, **data)
# 
#     async def _request(self, method, uri, allowed_statuses=(200, 201), **data) -> Response:
#         method, url, data = self._modify_request(method, self.root + str(uri).lstrip('/'), data)
#         kwargs = {}
#         headers = data.pop('headers_', None)
#         if headers is not None:
#             kwargs['headers'] = headers
#         if timeout := data.pop('timeout_', None):
#             kwargs['timeout'] = timeout
#         r = await glove.http.request(method, url, json=data or None, **kwargs)
#         if isinstance(allowed_statuses, int):
#             allowed_statuses = (allowed_statuses,)
#         if allowed_statuses != '*' and r.status_code not in allowed_statuses:
#             data = {
#                 'request_real_url': str(r.request.url),
#                 'request_headers': dict(r.request.headers),
#                 'request_data': data,
#                 'response_headers': dict(r.headers),
#                 'response_content': lenient_json(r.text),
#             }
#             logger.warning(
#                 '%s unexpected response %s /%s -> %s',
#                 self.__class__.__name__,
#                 method,
#                 uri,
#                 r.status_code,
#                 extra={'data': data} if self.settings.verbose_http_errors else {},
#             )
#             raise ApiError(method, url, r.status_code, r.text)
#         else:
#             logger.debug('%s /%s -> %s', method, uri, r.status_code)
#             return r
# 
#     def _modify_request(self, method, url, data):
#         return method, url, data
# 
# Path: tests/test_user_display.py
# def modify_url(url, settings, company='foobar'):
#     args = dict(company=company, expires=round(datetime(2032, 1, 1).timestamp()))
#     body = '{company}:{expires}'.format(**args).encode()
#     args['signature'] = hmac.new(settings.user_auth_key, body, hashlib.sha256).hexdigest()
#     return str(url) + ('&' if '?' in str(url) else '?') + urlencode(args)


# Path: tests/test_aux.py
import base64
import pytest
from foxglove.db.helpers import SyncDb
from foxglove.test_server import DummyServer
from foxglove.testing import Client
from starlette.testclient import TestClient
from src.ext import ApiError, ApiSession
from tests.test_user_display import modify_url



def test_robots(cli: TestClient):
    r = cli.get('/robots.txt')
    assert r.status_code == 200
    assert 'User-agent: *' in r.text


def test_favicon(cli: TestClient):
    r = cli.get('/favicon.ico', allow_redirects=False)
    assert r.status_code == 200
    assert 'image' in r.headers['Content-Type']  # value can vary


def test_405(cli: TestClient):
    r = cli.post('/')
    assert r.status_code == 405, r.text


def test_create_subaccount_new_few_sent(cli: Client, sync_db: SyncDb, dummy_server: DummyServer):
    data = {'company_code': 'foobar'}
    r = cli.post('/create-subaccount/email-mandrill/', json=data, headers={'Authorization': 'testing-key'})
    assert r.status_code == 201, r.text
    assert r.json() == {'message': 'subaccount created'}
    assert dummy_server.log == ['POST /mandrill/subaccounts/add.json > 200']

    r = cli.post('/create-subaccount/email-mandrill/', json=data, headers={'Authorization': 'testing-key'})
    assert r.status_code == 200, r.text
    assert r.json() == {
        'message': 'subaccount already exists with only 42 emails sent, reuse of subaccount id permitted'

    }