from typing import Awaitable, Callable, Dict, List

import aiohttp.web

from smb.common.multiruntime.lib.io import setup_filesystem
from smb.common.multiruntime.lib.revision import revision

from maps_adv.adv_store.client.lib.client import Client as AdvStoreClient
from maps_adv.common.third_party_clients.juggler import JugglerClient
from maps_adv.common.helpers.dsn_parser import parse
from maps_adv.common.lasagna import Lasagna
from maps_adv.warden.client.lib import TaskContext

from . import api, tasks
from .api_provider import ApiProvider
from .ch_query_log import ClickHouseQueryLog
from .data_manager import AbstractDataManager, DataManager
from .db import DB
from .domain import Domain

__all__ = ["Application"]

setup_filesystem("maps_adv/statistics/dashboard/server/")


class Application(Lasagna):
    SWIM_ENGINE_CLS = DB

    TASKS: Dict[str, Callable[[TaskContext, dict], Awaitable[None]]] = {
        "sync_category_search_reports": tasks.sync_category_search_reports,
        "stat_tasks_starter__report_campaigns_not_spending_budget": tasks.check_not_spending_budget,  # noqa: E501
        "dashboard__report_overdraft": tasks.check_overdraft,
    }
    TASKS_KWARGS_KEYS: List[str] = ["config", "ch_config", "dm", "domain"]

    build_revision: int
    config: dict
    ch_config: dict
    dm: AbstractDataManager
    ch_query_log: ClickHouseQueryLog
    domain: Domain

    async def _setup_layers(self, db: DB) -> aiohttp.web.Application:
        self.build_revision = revision
        self.ch_config = ch_config = parse(self.config["CH_STAT_DATABASE_URL"])
        ch_config["alt_hosts"] = ",".join(
            f"{h['host']}:{h['port']}" for h in ch_config["hosts"]
        )
        ch_config["password"] = self.config["CH_STORAGE_PASSWORD"]
        if ch_config["secure"] and not ch_config["ca_certs"]:
            ch_config["ca_certs"] = self.config["SSL_CERT_FILE"]

        self.dm = DataManager(
            ch_config=self.ch_config,
            table=self.config["CH_STORAGE_TABLE"],
            aggregated_table=self.config["CH_STORAGE_AGGREGATED_TABLE"],
            postgres_db=db,
            yql_config=dict(
                token=self.config["YQL_TOKEN"],
                cluster=self.config["YQL_CLUSTER"],
                category_search_report_table=self.config[
                    "YQL_CATEGORY_SEARCH_REPORT_TABLE"
                ],
                yt_pool=self.config["YT_POOL"],
            ),
            campaigns_only_for_v2=self.config["MONKEY_PATCH_CAMPAIGNS_ONLY_FOR_V2"],
            use_only_v2=self.config["MONKEY_PATCH_ALL_CAMPAIGNS_USE_V2"],
        )
        self.ch_query_log = ClickHouseQueryLog(
            database_url=self.config["CH_SYSTEM_DATABASE_URL"],
            ssl_cert_file=self.config["SSL_CERT_FILE"],
        )
        self.domain = Domain(
            self.dm,
            AdvStoreClient(self.config["ADV_STORE_URL"]),
            JugglerClient(
                self.config["JUGGLER_EVENTS_URL"], self.config["NANNY_SERVICE_ID"]
            ),
        )

        api_ = api.create(ApiProvider(self.dm, self.domain, self.ch_query_log))
        return api_
