"""URL whitelist management for fetch_url tool."""

import json
from pathlib import Path
from typing import Set, List, Optional
from urllib.parse import urlparse


class UrlWhitelistManager:
    """Manages allowed sites for the fetch_url tool."""

    def __init__(self):
        self.config_path = Path.home() / ".janito" / "url_whitelist.json"
        self._allowed_sites = self._load_whitelist()
        self._unrestricted_mode = False

    def set_unrestricted_mode(self, enabled: bool = True):
        """Enable or disable unrestricted mode (bypasses whitelist)."""
        self._unrestricted_mode = enabled

    def _load_whitelist(self) -> Set[str]:
        """Load the whitelist from config file."""
        if not self.config_path.exists():
            return set()

        try:
            with open(self.config_path, "r", encoding="utf-8") as f:
                data = json.load(f)
                return set(data.get("allowed_sites", []))
        except (json.JSONDecodeError, IOError):
            return set()

    def _save_whitelist(self):
        """Save the whitelist to config file."""
        self.config_path.parent.mkdir(parents=True, exist_ok=True)
        try:
            with open(self.config_path, "w", encoding="utf-8") as f:
                json.dump({"allowed_sites": list(self._allowed_sites)}, f, indent=2)
        except IOError:
            pass  # Silently fail if we can't write

    def is_url_allowed(self, url: str) -> bool:
        """Check if a URL is allowed based on the whitelist."""
        if self._unrestricted_mode:
            return True  # Unrestricted mode bypasses all whitelist checks

        if not self._allowed_sites:
            return True  # No whitelist means all sites allowed

        try:
            parsed = urlparse(url)
            domain = parsed.netloc.lower()

            # Check exact matches and subdomain matches
            for allowed in self._allowed_sites:
                allowed = allowed.lower()
                if domain == allowed or domain.endswith("." + allowed):
                    return True

            return False
        except Exception:
            return False  # Invalid URLs are blocked

    def add_allowed_site(self, site: str) -> bool:
        """Add a site to the whitelist."""
        # Clean up the site format
        site = site.strip().lower()
        if site.startswith("http://") or site.startswith("https://"):
            parsed = urlparse(site)
            site = parsed.netloc

        if site and site not in self._allowed_sites:
            self._allowed_sites.add(site)
            self._save_whitelist()
            return True
        return False

    def remove_allowed_site(self, site: str) -> bool:
        """Remove a site from the whitelist."""
        site = site.strip().lower()
        if site.startswith("http://") or site.startswith("https://"):
            parsed = urlparse(site)
            site = parsed.netloc

        if site in self._allowed_sites:
            self._allowed_sites.remove(site)
            self._save_whitelist()
            return True
        return False

    def get_allowed_sites(self) -> List[str]:
        """Get the list of allowed sites."""
        return sorted(self._allowed_sites)

    def set_allowed_sites(self, sites: List[str]):
        """Set the complete list of allowed sites."""
        self._allowed_sites = set()
        for site in sites:
            site = site.strip().lower()
            if site.startswith("http://") or site.startswith("https://"):
                parsed = urlparse(site)
                site = parsed.netloc
            if site:
                self._allowed_sites.add(site)
        self._save_whitelist()

    def clear_whitelist(self):
        """Clear all allowed sites."""
        self._allowed_sites.clear()
        self._save_whitelist()


# Global singleton
_url_whitelist_manager = None


def get_url_whitelist_manager() -> UrlWhitelistManager:
    """Get the global URL whitelist manager instance."""
    global _url_whitelist_manager
    if _url_whitelist_manager is None:
        _url_whitelist_manager = UrlWhitelistManager()
    return _url_whitelist_manager
