"""
Base URL Session - A requests.Session with automatic URL joining.

Provides a Session subclass that automatically joins a base URL with
relative paths, handling trailing/leading slashes correctly.

Example:
    from oaa.modules.base_url_session import BaseURLSession

    session = BaseURLSession("https://api.example.com/v1")
    session.headers.update({"Authorization": "Bearer token"})

    # These all work correctly:
    response = session.get("/users")      # → https://api.example.com/v1/users
    response = session.get("users")       # → https://api.example.com/v1/users
    response = session.post("/items", json={"name": "test"})

See Also:
    docs/howtos/how-to-write-a-fetch-function.md
    docs/howtos/how-to-add-a-rest-api-source.md
"""

import requests
import logging
from .exceptions import ConfigurationError

logger = logging.getLogger(__name__)


class BaseURLSession(requests.Session):
    """
    A requests.Session subclass that prepends a base URL to all requests.

    Handles URL joining correctly, including:
    - Ensures base_url ends with trailing slash
    - Strips leading slash from relative URLs
    - Logs joined URLs at DEBUG level

    Args:
        base_url: The base URL to prepend to all requests (required)

    Raises:
        ConfigurationError: If base_url is None or empty

    Example:
        session = BaseURLSession("https://api.example.com/v1")
        session.headers.update({"Authorization": "Bearer token"})

        # All HTTP methods work:
        response = session.get("/users")
        response = session.post("/items", json=data)
        response = session.put("/items/1", json=data)
        response = session.delete("/items/1")

    Common Usage Pattern:
        class MyAPI:
            def __init__(self, base_url):
                self._session = None
                self.base_url = base_url

            @property
            def session(self):
                if not self._session:
                    self._session = BaseURLSession(self.base_url)
                    self._session.headers.update(self.headers())
                return self._session

            def get(self, path, params=None, **kwargs):
                return self.session.get(path, params=params, **kwargs)
    """

    def __init__(self, base_url=None):
        """Initialize session with a base URL.

        Args:
            base_url: The base URL for all requests. A trailing slash
                     will be added if not present.

        Raises:
            ConfigurationError: If base_url is None or empty
        """
        super().__init__()
        if not base_url:
            raise ConfigurationError(
                "base_url is required and cannot be None or empty. "
                "Provide a valid base URL like 'https://api.example.com'"
            )
        self.base_url = base_url
        if self.base_url[-1] != "/":
            self.base_url += "/"

    def request(self, method, url, *args, **kwargs):
        """Make a request, joining the URL with base_url.

        Args:
            method: HTTP method (GET, POST, PUT, DELETE, etc.)
            url: Relative URL path (leading slash is optional)
            *args: Passed to requests.Session.request()
            **kwargs: Passed to requests.Session.request()

        Returns:
            requests.Response object

        Note:
            Uses string concatenation instead of urljoin to ensure
            the url parameter is always appended to base_url.
        """
        # Strip leading slash from url to avoid double slashes
        if url and url[0] == "/":
            url = url[1:]

        # Concatenate base_url (which ends with /) and url
        joined_url = self.base_url + url
        logger.debug("joined_url: %s", joined_url)

        return super().request(method, joined_url, *args, **kwargs)
