# Path: src/schemas/messages.py
# class SendMethod(str, Enum):
#     """
#     Should match SEND_METHODS sql enum
#     """
# 
#     email_mandrill = 'email-mandrill'
#     email_ses = 'email-ses'
#     email_test = 'email-test'
#     sms_messagebird = 'sms-messagebird'
#     sms_test = 'sms-test'
# 
# Path: src/schemas/webhooks.py
# class MandrillSingleWebhook(BaseWebhook):
#     ts: datetime
#     status: MandrillMessageStatus
#     message_id: IDStr
#     user_agent: str = None
#     location: dict = None
#     msg: dict = {}
# 
#     def extra_json(self, sort_keys=False):
#         return json.dumps(
#             {
#                 'user_agent': self.user_agent,
#                 'location': self.location,
#                 **{f: self.msg.get(f) for f in self.__config__.msg_fields},
#             },
#             sort_keys=sort_keys,
#         )
# 
#     class Config:
#         ignore_extra = True
#         fields = {'message_id': '_id', 'status': 'event'}
#         msg_fields = ('bounce_description', 'clicks', 'diag', 'reject', 'opens', 'resends', 'smtp_events', 'state')
# 
# class MessageBirdWebHook(BaseWebhook):
#     ts: datetime
#     status: MessageBirdMessageStatus
#     message_id: IDStr
#     error_code: str = None
# 
#     def extra_json(self, sort_keys=False):
#         return json.dumps({'error_code': self.error_code} if self.error_code else {}, sort_keys=sort_keys)
# 
#     class Config:
#         ignore_extra = True
#         fields = {'message_id': 'id', 'ts': 'statusDatetime', 'error_code': 'statusErrorCode'}
# 
# Path: src/views/common.py
# @app.get('/', response_class=HTMLResponse)
# @app.head('/', response_class=HTMLResponse)
# async def index(request: Request):
#     ctx = {k: escape(v) for k, v in glove.settings.dict(include={'commit', 'release_date', 'build_time'}).items()}
#     ctx['request'] = request
#     with open(templates_dir / 'index.jinja') as f:
#         html = Template(f.read()).render(**ctx)
#     return HTMLResponse(html)


import base64
import hashlib
import hmac
import json
from fastapi import APIRouter, Form, Header
from foxglove import glove
from foxglove.exceptions import HttpBadRequest, HttpForbidden, HttpUnprocessableEntity
from foxglove.route_class import KeepBodyAPIRoute
from pydantic import ValidationError
from starlette.requests import Request
from src.schemas.messages import SendMethod
from src.schemas.webhooks import MandrillSingleWebhook, MessageBirdWebHook
from src.views.common import index
async def mandrill_head_view(request: Request):
    return await index(request)


@app.post('/mandrill/')
async def mandrill_webhook_view(mandrill_events=Form(None), X_Mandrill_Signature: bytes = Header(None)):
    try:
        events = json.loads(mandrill_events)
    except ValueError:
        raise HttpBadRequest('Invalid data')
    msg = f'{glove.settings.mandrill_webhook_url}mandrill_events{mandrill_events}'
    sig_generated = base64.b64encode(
        hmac.new(glove.settings.mandrill_webhook_key.encode(), msg=msg.encode(), digestmod=hashlib.sha1).digest()
    )
    if not hmac.compare_digest(sig_generated, X_Mandrill_Signature):
        raise HttpForbidden('invalid signature')

    await glove.redis.enqueue_job('update_mandrill_webhooks', events)
    return 'message status updated\n'


@app.get('/messagebird/')
async def messagebird_webhook_view(request: Request):
    """
    Update messages sent with message bird
    """
    try:
        event = MessageBirdWebHook(**request.query_params)
    except ValidationError as e:
        raise HttpUnprocessableEntity(e.args[0])

# Path: src/schemas/messages.py
# class SendMethod(str, Enum):
#     """
#     Should match SEND_METHODS sql enum
#     """
# 
#     email_mandrill = 'email-mandrill'
#     email_ses = 'email-ses'
#     email_test = 'email-test'
#     sms_messagebird = 'sms-messagebird'
#     sms_test = 'sms-test'
# 
# Path: src/schemas/webhooks.py
# class MandrillSingleWebhook(BaseWebhook):
#     ts: datetime
#     status: MandrillMessageStatus
#     message_id: IDStr
#     user_agent: str = None
#     location: dict = None
#     msg: dict = {}
# 
#     def extra_json(self, sort_keys=False):
#         return json.dumps(
#             {
#                 'user_agent': self.user_agent,
#                 'location': self.location,
#                 **{f: self.msg.get(f) for f in self.__config__.msg_fields},
#             },
#             sort_keys=sort_keys,
#         )
# 
#     class Config:
#         ignore_extra = True
#         fields = {'message_id': '_id', 'status': 'event'}
#         msg_fields = ('bounce_description', 'clicks', 'diag', 'reject', 'opens', 'resends', 'smtp_events', 'state')
# 
# class MessageBirdWebHook(BaseWebhook):
#     ts: datetime
#     status: MessageBirdMessageStatus
#     message_id: IDStr
#     error_code: str = None
# 
#     def extra_json(self, sort_keys=False):
#         return json.dumps({'error_code': self.error_code} if self.error_code else {}, sort_keys=sort_keys)
# 
#     class Config:
#         ignore_extra = True
#         fields = {'message_id': 'id', 'ts': 'statusDatetime', 'error_code': 'statusErrorCode'}
# 
# Path: src/views/common.py
# @app.get('/', response_class=HTMLResponse)
# @app.head('/', response_class=HTMLResponse)
# async def index(request: Request):
#     ctx = {k: escape(v) for k, v in glove.settings.dict(include={'commit', 'release_date', 'build_time'}).items()}
#     ctx['request'] = request
#     with open(templates_dir / 'index.jinja') as f:
#         html = Template(f.read()).render(**ctx)
#     return HTMLResponse(html)


# Path: src/views/webhooks.py
import base64
import hashlib
import hmac
import json
from fastapi import APIRouter, Form, Header
from foxglove import glove
from foxglove.exceptions import HttpBadRequest, HttpForbidden, HttpUnprocessableEntity
from foxglove.route_class import KeepBodyAPIRoute
from pydantic import ValidationError
from starlette.requests import Request
from src.schemas.messages import SendMethod
from src.schemas.webhooks import MandrillSingleWebhook, MessageBirdWebHook
from src.views.common import index

async def mandrill_head_view(request: Request):
    return await index(request)


@app.post('/mandrill/')
async def mandrill_webhook_view(mandrill_events=Form(None), X_Mandrill_Signature: bytes = Header(None)):
    try:
        events = json.loads(mandrill_events)
    except ValueError:
        raise HttpBadRequest('Invalid data')
    msg = f'{glove.settings.mandrill_webhook_url}mandrill_events{mandrill_events}'
    sig_generated = base64.b64encode(
        hmac.new(glove.settings.mandrill_webhook_key.encode(), msg=msg.encode(), digestmod=hashlib.sha1).digest()
    )
    if not hmac.compare_digest(sig_generated, X_Mandrill_Signature):
        raise HttpForbidden('invalid signature')

    await glove.redis.enqueue_job('update_mandrill_webhooks', events)
    return 'message status updated\n'


@app.get('/messagebird/')
async def messagebird_webhook_view(request: Request):
    """
    Update messages sent with message bird
    """
    try:
        event = MessageBirdWebHook(**request.query_params)
    except ValidationError as e:
        raise HttpUnprocessableEntity(e.args[0])

    await glove.redis.enqueue_job('update_message_status', SendMethod.sms_messagebird, event)