# Copyright (C) 2020 by Maike <maike@systemli.org>
# Copyright (C) 2020 by Cathy Hu <cathy.hu@fau.de>
# Copyright (C) 2020, 2023 by Thomas Lindner <tom@dl6tom.de>
# Copyright (C) 2020 by Martin Rey <martin.rey@mailbox.org>
#
# SPDX-License-Identifier: 0BSD

from argparse import ArgumentParser
from asyncio import run as asyncio_run
from email.parser import BytesParser
from email.policy import default
from email.utils import parseaddr
from logging import getLogger
from re import sub
from sys import stdin

from fastapi import status
from ormantic import NoMatch
from pytoml import load
from requests import post

from kibicara.config import config
from kibicara.platforms.email.model import Email, EmailSubscriber

logger = getLogger(__name__)


class Main:
    def __init__(self):
        parser = ArgumentParser()
        parser.add_argument(
            "-f",
            "--config",
            dest="configfile",
            default="/etc/kibicara.conf",
            help="path to config file",
        )
        # the MDA passes the recipient address as command line argument
        parser.add_argument("recipient")
        args = parser.parse_args()

        try:
            with open(args.configfile) as configfile:
                config.update(load(configfile))
        except FileNotFoundError:
            # run with default config
            pass

        # extract email from the recipient
        email_name = args.recipient.lower()

        asyncio_run(self.__run(email_name))

    async def __run(self, email_name):
        try:
            email = await Email.get(name=email_name)
        except NoMatch:
            logger.error("No recipient with this name")
            exit(1)

        # read mail from STDIN and parse to EmailMessage object
        message = BytesParser(policy=default).parsebytes(stdin.buffer.read())

        sender = ""
        if message.get("sender"):
            sender = message.get("sender")
        elif message.get("from"):
            sender = message.get("from")
        else:
            logger.error("No Sender of From header")
            exit(1)

        sender = parseaddr(sender)[1]
        if not sender:
            logger.error("Could not parse sender")
            exit(1)

        maybe_subscriber = await EmailSubscriber.filter(email=sender).all()
        if len(maybe_subscriber) != 1 or maybe_subscriber[0].hood.id != email.hood.id:
            logger.error("Not a subscriber")
            exit(1)

        # extract relevant data from mail
        text = sub(
            r"<[^>]*>",
            "",
            message.get_body(preferencelist=("plain", "html")).get_content(),
        )

        response = post(
            "{0}/api/hoods/{1}/email/messages/".format(
                config["root_url"], email.hood.pk
            ),
            json={"text": text, "secret": email.secret},
        )
        if response.status_code == status.HTTP_201_CREATED:
            exit(0)
        elif response.status_code == status.HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS:
            logger.error("Message was't accepted: {0}".format(text))
        elif response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY:
            logger.error("Malformed request: {0}".format(response.json()))
        elif response.status_code == status.HTTP_401_UNAUTHORIZED:
            logger.error("Wrong API secret. kibicara_mda seems to be misconfigured")
        else:
            logger.error(
                "REST-API failed with response status {0}".format(response.status_code)
            )
        exit(1)