# Path: src/schemas/messages.py
# class EmailRecipientModel(BaseModel):
#     first_name: str = None
#     last_name: str = None
#     user_link: str = None
#     address: str = ...
#     tags: List[str] = []
#     context: dict = {}
#     headers: dict = {}
#     pdf_attachments: List[PDFAttachmentModel] = []
#     attachments: List[AttachmentModel] = []
# 
#     class Config:
#         max_anystr_length = int(1e7)
# 
# Path: src/worker/email.py
# STYLES_SASS = (THIS_DIR / 'extra' / 'default-styles.scss').read_text()
# def utcnow():
#     def __init__(self, ctx: dict, group_id: int, company_id: int, recipient: EmailRecipientModel, m: EmailSendModel):
#     async def run(self):
#     async def _send_mandrill(self, email_info: EmailInfo, attachments: List[dict]):
#     async def _send_test_email(self, email_info: EmailInfo, attachments: List[dict]):
#     async def _render_email(self, context, headers) -> Optional[EmailInfo]:
#     async def _generate_base64_pdf(self, pdf_attachments):
#     async def _generate_base64(self, attachments: List[AttachmentModel]):
#     async def _store_email(self, external_id, send_ts, email_info: EmailInfo):
#     async def _store_email_failed(self, status: MessageStatus, error_msg):
# async def send_email(ctx, group_id: int, company_id: int, recipient: EmailRecipientModel, m: EmailSendModel):
# class SendEmail:
# 
# Path: src/worker/scheduler.py
# async def delete_old_emails(ctx):
#     if not glove.settings.delete_old_emails:
#         logger.info('settings.delete_old_emails False, not running')
#         return
#     async with glove.pg.acquire() as conn:
#         count = await conn.execute_b(
#             'delete from message_groups where id in (select id from message_groups where created_ts < :cutoff)',
#             cutoff=datetime.now() - timedelta(days=365),
#         )
#     logger.info('deleted %s old messages', count.replace('DELETE ', ''))


import base64
import hashlib
import hmac
import json
import pytest
import re
from arq import Retry
from buildpg import V
from datetime import datetime, timedelta, timezone
from foxglove.db.helpers import SyncDb
from pathlib import Path
from pytest_toolbox.comparison import AnyInt, RegexStr
from starlette.testclient import TestClient
from uuid import uuid4
from src.schemas.messages import EmailRecipientModel
from src.worker import delete_old_emails, email_retrying, send_email as worker_send_email

    events = sync_db.fetch('select * from events')
    assert events[0]['ts'] == datetime(2032, 6, 1, 0, 0, tzinfo=timezone.utc)
    assert events[0]['status'] == 'open'


def test_mandrill_webhook_invalid(cli: TestClient, send_email, sync_db: SyncDb, dummy_server, settings):
    send_email(method='email-mandrill', recipients=[{'address': 'testing@example.org'}])
    messages = [{'ts': 1969660800, 'event': 'open', '_id': 'e587306</div></body><meta name=', 'foobar': ['x']}]
    data = {'mandrill_events': messages}

    msg = (
        'https://localhost/webhook/mandrill/mandrill_events[{"ts": 1969660800, "event": "open", '
        '"_id": "e587306</div></body><meta name=", "foobar": ["x"]}]'
    )
    sig = base64.b64encode(
        hmac.new(settings.mandrill_webhook_key.encode(), msg=msg.encode(), digestmod=hashlib.sha1).digest()
    )
    r = cli.post('/webhook/mandrill/', data=data, headers={'X-Mandrill-Signature': sig.decode()})
    assert r.status_code == 400, r.text

    assert sync_db.fetchval('select count(*) from events') == 0


def test_mandrill_send_bad_template(cli: TestClient, send_email, sync_db: SyncDb, dummy_server):
    assert sync_db.fetchval('select count(*) from messages') == 0
    send_email(
        method='email-mandrill', main_template='{{ foo } test message', recipients=[{'address': 'foobar_b@testing.com'}]
    )
    message = sync_db.fetchrow_b('select * from messages')

# Path: src/schemas/messages.py
# class EmailRecipientModel(BaseModel):
#     first_name: str = None
#     last_name: str = None
#     user_link: str = None
#     address: str = ...
#     tags: List[str] = []
#     context: dict = {}
#     headers: dict = {}
#     pdf_attachments: List[PDFAttachmentModel] = []
#     attachments: List[AttachmentModel] = []
# 
#     class Config:
#         max_anystr_length = int(1e7)
# 
# Path: src/worker/email.py
# STYLES_SASS = (THIS_DIR / 'extra' / 'default-styles.scss').read_text()
# def utcnow():
#     def __init__(self, ctx: dict, group_id: int, company_id: int, recipient: EmailRecipientModel, m: EmailSendModel):
#     async def run(self):
#     async def _send_mandrill(self, email_info: EmailInfo, attachments: List[dict]):
#     async def _send_test_email(self, email_info: EmailInfo, attachments: List[dict]):
#     async def _render_email(self, context, headers) -> Optional[EmailInfo]:
#     async def _generate_base64_pdf(self, pdf_attachments):
#     async def _generate_base64(self, attachments: List[AttachmentModel]):
#     async def _store_email(self, external_id, send_ts, email_info: EmailInfo):
#     async def _store_email_failed(self, status: MessageStatus, error_msg):
# async def send_email(ctx, group_id: int, company_id: int, recipient: EmailRecipientModel, m: EmailSendModel):
# class SendEmail:
# 
# Path: src/worker/scheduler.py
# async def delete_old_emails(ctx):
#     if not glove.settings.delete_old_emails:
#         logger.info('settings.delete_old_emails False, not running')
#         return
#     async with glove.pg.acquire() as conn:
#         count = await conn.execute_b(
#             'delete from message_groups where id in (select id from message_groups where created_ts < :cutoff)',
#             cutoff=datetime.now() - timedelta(days=365),
#         )
#     logger.info('deleted %s old messages', count.replace('DELETE ', ''))


# Path: tests/test_email.py
import base64
import hashlib
import hmac
import json
import pytest
import re
from arq import Retry
from buildpg import V
from datetime import datetime, timedelta, timezone
from foxglove.db.helpers import SyncDb
from pathlib import Path
from pytest_toolbox.comparison import AnyInt, RegexStr
from starlette.testclient import TestClient
from uuid import uuid4
from src.schemas.messages import EmailRecipientModel
from src.worker import delete_old_emails, email_retrying, send_email as worker_send_email


    events = sync_db.fetch('select * from events')
    assert events[0]['ts'] == datetime(2032, 6, 1, 0, 0, tzinfo=timezone.utc)
    assert events[0]['status'] == 'open'


def test_mandrill_webhook_invalid(cli: TestClient, send_email, sync_db: SyncDb, dummy_server, settings):
    send_email(method='email-mandrill', recipients=[{'address': 'testing@example.org'}])
    messages = [{'ts': 1969660800, 'event': 'open', '_id': 'e587306</div></body><meta name=', 'foobar': ['x']}]
    data = {'mandrill_events': messages}

    msg = (
        'https://localhost/webhook/mandrill/mandrill_events[{"ts": 1969660800, "event": "open", '
        '"_id": "e587306</div></body><meta name=", "foobar": ["x"]}]'
    )
    sig = base64.b64encode(
        hmac.new(settings.mandrill_webhook_key.encode(), msg=msg.encode(), digestmod=hashlib.sha1).digest()
    )
    r = cli.post('/webhook/mandrill/', data=data, headers={'X-Mandrill-Signature': sig.decode()})
    assert r.status_code == 400, r.text

    assert sync_db.fetchval('select count(*) from events') == 0


def test_mandrill_send_bad_template(cli: TestClient, send_email, sync_db: SyncDb, dummy_server):
    assert sync_db.fetchval('select count(*) from messages') == 0
    send_email(
        method='email-mandrill', main_template='{{ foo } test message', recipients=[{'address': 'foobar_b@testing.com'}]
    )
    message = sync_db.fetchrow_b('select * from messages')

    assert message['status'] == 'render_failed'