"""Script entry point."""

import argparse
from typing import (
    IO,
    List,
)

from aiohttp.web import Application
from argcomplete import autocomplete
from prometheus_aioexporter import (
    MetricConfig,
    PrometheusExporterScript,
)
from prometheus_aioexporter.metric import InvalidMetricType
from toolrack.script import ErrorExitMessage

from . import __version__
from .config import (
    Config,
    ConfigError,
    load_config,
)
from .loop import QueryLoop


class QueryExporterScript(PrometheusExporterScript):
    """Periodically run database queries and export results to Prometheus."""

    name = "query-exporter"
    description = __doc__
    default_port = 9560

    def configure_argument_parser(self, parser: argparse.ArgumentParser):
        parser.add_argument(
            "config", type=argparse.FileType("r"), help="configuration file"
        )
        parser.add_argument(
            "-V", "--version", action="version", version=f"%(prog)s {__version__}",
        )
        parser.add_argument(
            "--check-only",
            action="store_true",
            help="only check configuration, don't run the exporter",
        )
        autocomplete(parser)

    def configure(self, args: argparse.Namespace):
        config = self._load_config(args.config)
        if args.check_only:
            self.exit()
        self.create_metrics(config.metrics.values())
        self.query_loop = QueryLoop(config, self.registry, self.logger)

    async def on_application_startup(self, application: Application):
        application["exporter"].set_metric_update_handler(self._update_handler)
        await self.query_loop.start()

    async def on_application_shutdown(self, application: Application):
        await self.query_loop.stop()

    async def _update_handler(self, metrics: List[MetricConfig]):
        """Run queries with no specified schedule on each request."""
        await self.query_loop.run_aperiodic_queries()

    def _load_config(self, config_file: IO) -> Config:
        """Load the application configuration."""
        try:
            config = load_config(config_file, self.logger)
        except (InvalidMetricType, ConfigError) as error:
            raise ErrorExitMessage(str(error))
        finally:
            config_file.close()
        return config


script = QueryExporterScript()