"""
ID Wispera Slack Integration
Manages Slack bot tokens, webhook URLs, and app-level tokens as governed passports

Usage:
    from id_wispera.integrations.slack import WisperaSlackProvider

    provider = WisperaSlackProvider()
    bot_token = provider.get_bot_token("my-slack-bot")
"""

from typing import Optional, Any
from id_wispera.integrations.base import WisperaBaseProvider


class WisperaSlackProvider(WisperaBaseProvider):
    """
    Slack credential provider.
    Manages bot tokens, user tokens, app-level tokens, and webhook URLs.
    """

    def __init__(
        self,
        vault_path: Optional[str] = None,
        passphrase: Optional[str] = None,
        passphrase_env: str = "IDW_PASSPHRASE",
    ):
        super().__init__(
            vault_path=vault_path,
            passphrase=passphrase,
            passphrase_env=passphrase_env,
            actor="slack",
        )

    def get_bot_token(self, passport_name: str = "slack-bot") -> str:
        """
        Get a Slack bot token (xoxb-...).

        Args:
            passport_name: Name of the passport

        Returns:
            The bot token string
        """
        return self.get(passport_name, purpose="Slack bot token access")

    def get_app_token(self, passport_name: str = "slack-app") -> str:
        """
        Get a Slack app-level token (xapp-...).

        Args:
            passport_name: Name of the passport

        Returns:
            The app-level token string
        """
        return self.get(passport_name, purpose="Slack app-level token access")

    def get_user_token(self, passport_name: str = "slack-user") -> str:
        """
        Get a Slack user token (xoxp-...).

        Args:
            passport_name: Name of the passport

        Returns:
            The user token string
        """
        return self.get(passport_name, purpose="Slack user token access")

    def get_webhook_url(self, passport_name: str = "slack-webhook") -> str:
        """
        Get a Slack webhook URL.

        Args:
            passport_name: Name of the passport

        Returns:
            The webhook URL string
        """
        return self.get(passport_name, purpose="Slack webhook URL access")

    def get_slack_credential(self, passport_name: str) -> dict[str, Any]:
        """
        Get a typed Slack credential with token type detection.

        Args:
            passport_name: Name of the passport

        Returns:
            Dict with value, token_type, and team_id
        """
        passport = self._get_passport(passport_name)

        self._log_access_entry(
            passport.id,
            "slack",
            "Slack credential access",
        )

        value = passport.credential_value
        token_type = self._detect_token_type(value)
        tags = getattr(passport, "tags", [])
        team_id = self._extract_team_id(tags)

        return {
            "value": value,
            "token_type": token_type,
            "team_id": team_id,
        }

    def list_slack_credentials(self) -> list[str]:
        """
        List all available Slack credentials.

        Returns:
            List of passport names that are Slack-related
        """
        vault = self._ensure_vault()
        passports = vault.list_passports()

        names = []
        for passport in passports:
            if passport.status not in ("active", "expiring"):
                continue
            tags = getattr(passport, "tags", [])
            cred_type = getattr(passport, "credential_type", "")
            if (
                "slack" in tags
                or cred_type == "bot-token"
                or "slack" in passport.name.lower()
            ):
                names.append(passport.name)

        return names

    def get_socket_mode_tokens(
        self,
        bot_passport_name: str = "slack-bot",
        app_passport_name: str = "slack-app",
    ) -> dict[str, str]:
        """
        Get bot + app tokens for Slack Socket Mode.

        Args:
            bot_passport_name: Name of the bot token passport
            app_passport_name: Name of the app token passport

        Returns:
            Dict with bot_token and app_token
        """
        return {
            "bot_token": self.get_bot_token(bot_passport_name),
            "app_token": self.get_app_token(app_passport_name),
        }

    def _detect_token_type(self, value: str) -> str:
        """Detect the type of a Slack token from its prefix."""
        if value.startswith("xoxb-"):
            return "bot"
        if value.startswith("xoxp-"):
            return "user"
        if value.startswith("xapp-"):
            return "app-level"
        if value.startswith("https://hooks.slack.com/"):
            return "webhook"
        return "bot"

    def _extract_team_id(self, tags: list[str]) -> Optional[str]:
        """Extract team/workspace ID from passport tags."""
        for tag in tags:
            if tag.startswith("team:"):
                return tag[5:]
            if tag.startswith("workspace:"):
                return tag[10:]
        return None
