"""Smart crawler with automatic fallback between methods."""

import re
from pathlib import Path
from urllib.parse import urlparse

from .web_crawler import WebCrawler
from .github_crawler import GitHubCrawler
from .firecrawl_crawler import FirecrawlCrawler


class SmartCrawler:
    """
    Intelligent crawler that automatically tries different methods.
    
    Fallback chain:
    1. HTTP (fast, works for most sites)
    2. GitHub (if URL is github or project has github repo)
    3. Firecrawl (for protected sites, requires Docker or API key)
    """
    
    def __init__(
        self,
        output_dir: Path,
        max_depth: int = 3,
        max_pages: int = 100,
        firecrawl_url: str = "http://localhost:3002",
        firecrawl_key: str | None = None,
    ):
        self.output_dir = Path(output_dir)
        self.max_depth = max_depth
        self.max_pages = max_pages
        self.firecrawl_url = firecrawl_url
        self.firecrawl_key = firecrawl_key
    
    def crawl(self, url: str) -> dict:
        """
        Crawl URL using smart fallback.
        
        Returns result from first successful method.
        """
        self.output_dir.mkdir(parents=True, exist_ok=True)
        
        # Check if it's a GitHub URL
        if self._is_github_url(url):
            print("📦 Detected GitHub URL, using GitHub crawler...")
            return self._try_github(url)
        
        # 1. Try HTTP first
        print("🌐 Trying HTTP crawler...")
        result = self._try_http(url)
        
        if result["pages_count"] > 0:
            return result
        
        print("⚠️  HTTP failed or returned empty content")
        
        # 2. Try to find GitHub repo for this project
        github_url = self._find_github_repo(url)
        if github_url:
            print(f"📦 Found GitHub repo: {github_url}")
            result = self._try_github(github_url)
            
            if result["pages_count"] > 0:
                return result
            
            print("⚠️  GitHub crawler returned no pages")
        
        # 3. Try Firecrawl
        print("🔥 Trying Firecrawl...")
        result = self._try_firecrawl(url)
        
        if result["pages_count"] > 0:
            return result
        
        print("❌ All methods failed")
        return {"pages_count": 0, "output_dir": str(self.output_dir), "pages": []}
    
    def _is_github_url(self, url: str) -> bool:
        """Check if URL is a GitHub URL."""
        parsed = urlparse(url)
        return "github.com" in parsed.netloc or parsed.netloc.endswith(".github.io")
    
    def _try_http(self, url: str) -> dict:
        """Try HTTP crawler."""
        try:
            crawler = WebCrawler(
                output_dir=self.output_dir,
                max_depth=self.max_depth,
                max_pages=self.max_pages
            )
            return crawler.crawl(url)
        except Exception as e:
            print(f"   HTTP error: {e}")
            return {"pages_count": 0, "output_dir": str(self.output_dir), "pages": []}
    
    def _try_github(self, url: str) -> dict:
        """Try GitHub crawler."""
        try:
            crawler = GitHubCrawler(
                output_dir=self.output_dir,
                max_pages=self.max_pages
            )
            return crawler.crawl(url)
        except Exception as e:
            print(f"   GitHub error: {e}")
            return {"pages_count": 0, "output_dir": str(self.output_dir), "pages": []}
    
    def _try_firecrawl(self, url: str) -> dict:
        """Try Firecrawl crawler."""
        try:
            crawler = FirecrawlCrawler(
                output_dir=self.output_dir,
                max_depth=self.max_depth,
                max_pages=self.max_pages,
                api_url=self.firecrawl_url,
                api_key=self.firecrawl_key
            )
            return crawler.crawl(url)
        except Exception as e:
            print(f"   Firecrawl error: {e}")
            return {"pages_count": 0, "output_dir": str(self.output_dir), "pages": []}
    
    def _find_github_repo(self, url: str) -> str | None:
        """
        Try to find GitHub repo for a documentation site.
        
        Common patterns:
        - docs.project.com -> github.com/project/project
        - project.readthedocs.io -> github.com/*/project
        """
        parsed = urlparse(url)
        domain = parsed.netloc.lower()
        
        # Common doc site patterns
        patterns = [
            # docs.anthropic.com -> anthropic
            (r"docs\.([^.]+)\.", lambda m: m.group(1)),
            # anthropic.github.io -> anthropic
            (r"([^.]+)\.github\.io", lambda m: m.group(1)),
            # project.readthedocs.io -> project
            (r"([^.]+)\.readthedocs\.io", lambda m: m.group(1)),
        ]
        
        for pattern, extractor in patterns:
            match = re.search(pattern, domain)
            if match:
                project = extractor(match)
                
                # Try common GitHub patterns
                github_urls = [
                    f"https://github.com/{project}/{project}",
                    f"https://github.com/{project}ai/{project}",  # projectai/project
                ]
                
                for github_url in github_urls:
                    if self._github_repo_exists(github_url):
                        return github_url
        
        return None
    
    def _github_repo_exists(self, url: str) -> bool:
        """Check if GitHub repo exists."""
        import httpx
        
        try:
            # Extract owner/repo from URL
            parts = urlparse(url).path.strip("/").split("/")
            if len(parts) >= 2:
                api_url = f"https://api.github.com/repos/{parts[0]}/{parts[1]}"
                with httpx.Client(timeout=5.0) as client:
                    response = client.get(api_url)
                    return response.status_code == 200
        except:
            pass
        
        return False
