import os
from urllib.parse import urlparse

from cleo.events.console_events import COMMAND
from cleo.events.event import Event
from cleo.events.event_dispatcher import EventDispatcher
from cleo.io.io import IO
from poetry.console.application import Application
from poetry.console.commands.installer_command import InstallerCommand
from poetry.plugins.application_plugin import ApplicationPlugin
from poetry.repositories.pypi_repository import PyPiRepository

from poetry_dynamic_caching.DevPiRepository import DevPiRepository


class DynamicCachingPlugin(ApplicationPlugin):
    def __init__(self):
        self.application: Application|None = None
        self.io: IO|None = None
        super().__init__()

    def activate(self, application: Application):
        self.application = application
        application.event_dispatcher.add_listener(
            COMMAND, self.on_command
        )

    def _replace_pypi_repo_url(self, devpi_repo: DevPiRepository):
        for repo in self.application.poetry.pool.repositories:
            if isinstance(repo, PyPiRepository):
                self.io.write_line(f"<debug>Replacing url of repository {repo.name} with {devpi_repo.url}</debug>")
                self.application.poetry.pool.remove_repository(repo.name)
                self.application.poetry.pool.add_repository(devpi_repo)

    def _validate_url(self, url: str) -> bool:
        try:
            result = urlparse(url)
            return all([result.scheme, result.netloc])
        except ValueError:
            self.io.write_line(f"<debug>[Warning] URL {url} is malformed.</debug>")
            return False

    def on_command(
        self,
        event: Event,
        event_name: str,
        dispatcher: EventDispatcher
    ) -> None:
        command = event.command
        if not isinstance(command, InstallerCommand):
            return

        self.io = event.io
        poetry = command.poetry

        env_devpi_url = os.environ.get("DEVPI_URL")
        if env_devpi_url:
            devpi_urls = [env_devpi_url]
        else:
            config = self._get_plugin_config(poetry)
            try:
                devpi_urls = [c.get("url") for c in config.get("cache") if c.get("type") == "devpi"]
            except KeyError:
                self.io.write_line("<debug>Malformed configuration.</debug>")
                return

        for devpi_url in devpi_urls:
            if not self._validate_url(devpi_url):
                return

        devpi_repo = None
        for devpi_url in devpi_urls:
            devpi_repo = DevPiRepository(devpi_url, config=self.application.poetry.config)
            if devpi_repo.is_available():
                break

        self.io.write_line(f"<debug>Cache status: {'Available' if devpi_repo is not None else 'Unavailable'}</debug>")

        if devpi_repo is not None:
            self._replace_pypi_repo_url(devpi_repo)

    def _get_plugin_config(self, poetry) -> dict:
        """Read plugin configuration from pyproject.toml [tool.poetry-dynamic-caching] section."""
        pyproject_data = poetry.pyproject.data
        tool_config = pyproject_data.get("tool", {})
        return tool_config.get("poetry-dynamic-caching", {})
