"""
Generic PDF Downloader for unspecified sources
"""

from typing import Optional
import requests
from urllib.parse import urlparse
from loguru import logger

from .base import BaseDownloader, ContentType, DownloadResult


class GenericDownloader(BaseDownloader):
    """Generic downloader for any URL - attempts basic PDF download."""

    def can_handle(self, url: str) -> bool:
        """Generic downloader can handle any URL as a fallback."""
        return True

    def download(
        self, url: str, content_type: ContentType = ContentType.PDF
    ) -> Optional[bytes]:
        """Attempt to download content from any URL."""
        if content_type == ContentType.TEXT:
            # For generic sources, we can only extract text from PDF
            pdf_content = self._download_pdf(url)
            if pdf_content:
                text = self.extract_text_from_pdf(pdf_content)
                if text:
                    return text.encode("utf-8")
            return None
        else:
            # Try to download as PDF
            return self._download_pdf(url)

    def download_with_result(
        self, url: str, content_type: ContentType = ContentType.PDF
    ) -> DownloadResult:
        """Download content and return detailed result with skip reason."""
        if content_type == ContentType.TEXT:
            # For generic sources, we can only extract text from PDF
            pdf_content = self._download_pdf(url)
            if pdf_content:
                text = self.extract_text_from_pdf(pdf_content)
                if text:
                    return DownloadResult(
                        content=text.encode("utf-8"), is_success=True
                    )
                else:
                    return DownloadResult(
                        skip_reason="PDF downloaded but text extraction failed"
                    )
            return DownloadResult(skip_reason="Could not download PDF from URL")
        else:
            # Try to download as PDF
            logger.info(f"Attempting generic download from {url}")

            # Try direct download
            pdf_content = super()._download_pdf(url)

            if pdf_content:
                logger.info(f"Successfully downloaded PDF from {url}")
                return DownloadResult(content=pdf_content, is_success=True)

            # If the URL doesn't end with .pdf, try adding it
            try:
                parsed = urlparse(url)
                if not parsed.path.endswith(".pdf"):
                    pdf_url = url.rstrip("/") + ".pdf"
                    logger.debug(f"Trying with .pdf extension: {pdf_url}")
                    pdf_content = super()._download_pdf(pdf_url)
                else:
                    pdf_content = None
            except (ValueError, AttributeError):
                # urlparse can raise ValueError for malformed URLs
                pdf_content = None

            if pdf_content:
                logger.info(f"Successfully downloaded PDF from {pdf_url}")
                return DownloadResult(content=pdf_content, is_success=True)

            # Try to determine more specific reason
            try:
                response = self.session.get(
                    url, timeout=5, allow_redirects=True, stream=True
                )

                # Check status code
                if response.status_code == 200:
                    # Check if it's HTML instead of PDF
                    content_type = response.headers.get(
                        "content-type", ""
                    ).lower()
                    if "text/html" in content_type:
                        return DownloadResult(
                            skip_reason="Article page requires login or subscription - no direct PDF link available"
                        )
                    else:
                        return DownloadResult(
                            skip_reason=f"Unexpected content type: {content_type} - expected PDF"
                        )
                elif response.status_code == 404:
                    return DownloadResult(
                        skip_reason="Article not found (404) - may have been removed or URL is incorrect"
                    )
                elif response.status_code == 403:
                    return DownloadResult(
                        skip_reason="Access denied (403) - article requires subscription or special permissions"
                    )
                elif response.status_code == 401:
                    return DownloadResult(
                        skip_reason="Authentication required - please login to access this article"
                    )
                elif response.status_code >= 500:
                    return DownloadResult(
                        skip_reason=f"Server error ({response.status_code}) - website is experiencing technical issues"
                    )
                else:
                    return DownloadResult(
                        skip_reason=f"Unable to access article - server returned error code {response.status_code}"
                    )
            except requests.exceptions.Timeout:
                return DownloadResult(
                    skip_reason="Connection timed out - server took too long to respond"
                )
            except requests.exceptions.ConnectionError:
                return DownloadResult(
                    skip_reason="Could not connect to server - website may be down"
                )
            except requests.RequestException:
                logger.warning("Unexpected error checking URL: %s", url)
                return DownloadResult(
                    skip_reason="Network error - could not reach the website"
                )

    def _download_pdf(self, url: str) -> Optional[bytes]:
        """Attempt to download PDF from URL."""
        logger.info(f"Attempting generic download from {url}")

        # Try direct download
        pdf_content = super()._download_pdf(url)

        if pdf_content:
            logger.info(f"Successfully downloaded PDF from {url}")
            return pdf_content

        # If the URL doesn't end with .pdf, try adding it
        try:
            parsed = urlparse(url)
            if not parsed.path.endswith(".pdf"):
                pdf_url = url.rstrip("/") + ".pdf"
                logger.debug(f"Trying with .pdf extension: {pdf_url}")
                pdf_content = super()._download_pdf(pdf_url)
            else:
                pdf_content = None
        except (ValueError, AttributeError):
            # urlparse can raise ValueError for malformed URLs
            pdf_content = None

        if pdf_content:
            logger.info(f"Successfully downloaded PDF from {pdf_url}")
            return pdf_content

        logger.warning(f"Failed to download PDF from {url}")
        return None
