import asyncio

from aiohttp import web
from smb.common.multiruntime.lib.io import setup_filesystem

from maps_adv.common.email_sender import Client as EmailClient
from maps_adv.common.lasagna import Lasagna
from maps_adv.geosmb.clients.facade import FacadeIntClient
from maps_adv.geosmb.scenarist.server.lib.clients.fake_email_sender import (
    FakeEmailSenderClient,
)

from . import api, tasks
from .data_manager import BaseDataManager, DataManager
from .db import DB
from .domain import Domain

setup_filesystem("maps_adv/geosmb/scenarist/server/")
setup_filesystem("templates/", subdir="templates")


class Application(Lasagna):
    __slots__ = ("dm", "domain")
    SWIM_ENGINE_CLS = DB

    TASKS = {
        "geosmb_scenarist__export_subscriptions": tasks.SubscriptionsYtExportTask,
        "geosmb_scenarist__import_messages": tasks.MessagesYtImportTask,
        "geosmb_scenarist__process_unsent_emails": tasks.process_unsent_emails,
        "geosmb_scenarist__import_certificate_mailing_stats": tasks.CertificateMailingStatYtImportTask,  # noqa E501
        "geosmb_scenarist__export_subscriptions_versions": tasks.SubscriptionsVersionsYtExportTask,  # noqa E501
    }
    TASKS_KWARGS_KEYS = ["dm", "config", "domain"]

    dm: BaseDataManager
    domain: Domain

    async def _setup_layers(self, db: DB) -> web.Application:
        clients = {
            "tvm_client": self.tvm,
            "facade_client": await FacadeIntClient(
                url=self.config["FACADE_URL"],
                tvm=self.tvm,
                tvm_source="self",
                tvm_destination="facade",
            ),
        }

        if self.config["SEND_REAL_EMAILS"]:
            email_client_cls = EmailClient
        else:
            email_client_cls = FakeEmailSenderClient

        clients["email_client"] = email_client_cls(
            url=self.config["EMAIL_CLIENT_API_URL"],
            account_slug=self.config["EMAIL_CLIENT_ACCOUNT_SLUG"],
            account_token=self.config["EMAIL_CLIENT_ACCOUNT_TOKEN"],
        )

        self.dm = DataManager(db)
        self.domain = Domain(
            dm=self.dm,
            email_client=clients["email_client"],
            facade_client=clients["facade_client"],
            schedule_promo_campaign_params=dict(
                title=self.config["EMAIL_CLIENT_CAMPAIGN_TITLE"],
                from_name=self.config["EMAIL_CLIENT_FROM_NAME"],
                from_email=self.config["EMAIL_CLIENT_FROM_EMAIL"],
                unsubscribe_list_slug=self.config["EMAIL_CLIENT_UNSUBSCRIBE_LIST_SLUG"],
                allowed_stat_domains=list(
                    self.config["EMAIL_CLIENT_ALLOWED_STAT_DOMAINS"]
                )
                if self.config["EMAIL_CLIENT_ALLOWED_STAT_DOMAINS"] is not None
                else None,
            ),
            allowed_button_url_domains=self.config["EMAIL_CLIENT_ALLOWED_STAT_DOMAINS"],
        )

        _api = api.create(self.domain)
        _api.on_shutdown.append(
            lambda _: asyncio.gather(*[client.close() for client in clients.values()])
        )

        return _api
