"""
Main client class for interacting with the CreatorsArea.fr API.
"""

import requests
from typing import List, Optional, Dict, Any
from datetime import datetime

from .models import Job, Category
from .exceptions import APIError, NotFoundError, ValidationError


class CreatorsAreaClient:
    """
    Client for the CreatorsArea.fr job marketplace API.

    Example:
        >>> client = CreatorsAreaClient()
        >>> jobs = client.get_jobs(category="DEVELOPER", limit=10)
        >>> for job in jobs:
        ...     print(job.title, job.budget)
    """

    BASE_URL = "https://creatorsarea.fr"
    API_URL = f"{BASE_URL}/api/offers"
    DEFAULT_USER_AGENT = "creatorsarea-py/0.1.0 (Python SDK)"
    DEFAULT_TIMEOUT = 30

    def __init__(
        self,
        base_url: Optional[str] = None,
        user_agent: Optional[str] = None,
        timeout: int = DEFAULT_TIMEOUT,
    ):
        """
        Initialize the CreatorsArea client.

        Args:
            base_url: Override base URL (for testing)
            user_agent: Custom User-Agent string
            timeout: Request timeout in seconds
        """
        self.base_url = base_url or self.BASE_URL
        self.api_url = f"{self.base_url}/api/offers"
        self.user_agent = user_agent or self.DEFAULT_USER_AGENT
        self.timeout = timeout

        self.session = requests.Session()
        self.session.headers.update({
            "User-Agent": self.user_agent,
            "Accept": "application/json",
        })

    def get_jobs(
        self,
        category: str,
        limit: Optional[int] = None,
        min_budget: Optional[float] = None,
        max_budget: Optional[float] = None,
        exclude_volunteer: bool = False,
        tags: Optional[List[str]] = None,
        status: Optional[str] = None,
    ) -> List[Job]:
        """
        Fetch a list of jobs from CreatorsArea.

        Args:
            category: Job category ("DEVELOPER", "GRAPHISM", "TEAM")
            limit: Maximum number of jobs to return
            min_budget: Minimum budget filter
            max_budget: Maximum budget filter
            exclude_volunteer: Exclude volunteer/free jobs
            tags: Filter by specific tags
            status: Filter by status (e.g., "ACTIVE")

        Returns:
            List of Job objects

        Raises:
            ValidationError: Invalid parameters
            APIError: API request failed

        Example:
            >>> jobs = client.get_jobs(category="DEVELOPER", limit=5)
            >>> paid_jobs = client.get_jobs(
            ...     category="DEVELOPER",
            ...     min_budget=50.0,
            ...     exclude_volunteer=True
            ... )
        """
        # Validate category
        if category not in [c.value for c in Category]:
            raise ValidationError(
                f"Invalid category: {category}. "
                f"Must be one of: {[c.value for c in Category]}"
            )

        params = {"category": category}

        try:
            response = self.session.get(
                self.api_url,
                params=params,
                timeout=self.timeout,
            )
            response.raise_for_status()
            data = response.json()

        except requests.RequestException as e:
            raise APIError(f"Failed to fetch jobs: {e}") from e
        except ValueError as e:
            raise APIError(f"Invalid JSON response: {e}") from e

        results = data.get("results", [])
        jobs = []

        for offer in results:
            job = Job.from_api_response(offer, base_url=self.base_url)
            if not job:
                continue

            # Apply filters
            if min_budget is not None and job.budget_value < min_budget:
                continue
            if max_budget is not None and job.budget_value > max_budget:
                continue
            if exclude_volunteer and job.is_volunteer:
                continue
            if tags and not any(tag.lower() in [t.lower() for t in job.tags] for tag in tags):
                continue
            if status and job.status != status:
                continue

            jobs.append(job)

            # Apply limit
            if limit and len(jobs) >= limit:
                break

        return jobs

    def get_job_by_id(self, job_id: str) -> Optional[Job]:
        """
        Fetch a specific job by its ID.

        Args:
            job_id: The job ID

        Returns:
            Job object or None if not found

        Raises:
            APIError: API request failed

        Example:
            >>> job = client.get_job_by_id("675d123...")
            >>> if job:
            ...     print(job.title)
        """
        # Search through all categories
        for category in Category:
            jobs = self.get_jobs(category=category.value)
            for job in jobs:
                if job.id == job_id:
                    return job

        return None

    def get_job_by_slug(self, slug: str) -> Optional[Job]:
        """
        Fetch a specific job by its slug.

        Args:
            slug: The job slug (URL-friendly identifier)

        Returns:
            Job object or None if not found

        Raises:
            APIError: API request failed

        Example:
            >>> job = client.get_job_by_slug("developpeur-lua-gmod")
        """
        # Search through all categories
        for category in Category:
            jobs = self.get_jobs(category=category.value)
            for job in jobs:
                if job.slug == slug:
                    return job

        return None

    def get_all_jobs(
        self,
        category: str,
        **filters
    ) -> List[Job]:
        """
        Fetch all jobs with automatic pagination.

        Args:
            category: Job category
            **filters: Additional filters (same as get_jobs)

        Returns:
            List of all Job objects

        Example:
            >>> all_dev_jobs = client.get_all_jobs(category="DEVELOPER")
        """
        # CreatorsArea API doesn't seem to have explicit pagination
        # This method fetches all available jobs
        return self.get_jobs(category=category, **filters)

    def __enter__(self):
        """Context manager entry."""
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Context manager exit."""
        self.session.close()

    def close(self):
        """Close the HTTP session."""
        self.session.close()
