"""
Data models for CreatorsArea.fr API.
"""

from dataclasses import dataclass, field
from datetime import datetime
from typing import List, Optional, Dict, Any
from enum import Enum
from dateutil import parser as dateparser


class Category(Enum):
    """Job categories on CreatorsArea."""
    DEVELOPER = "DEVELOPER"
    GRAPHISM = "GRAPHISM"
    TEAM = "TEAM"


@dataclass
class Job:
    """
    Represents a job offer from CreatorsArea.

    Attributes:
        id: Unique job ID
        title: Job title
        slug: URL slug
        url: Full URL to job posting
        description: Short description
        content: Full job content/details
        category: Job category (localized)
        kind: Raw category from API
        status: Job status (ACTIVE, CLOSED, etc.)
        budget: Formatted budget string
        budget_value: Numeric budget value
        is_volunteer: Whether this is volunteer work
        budget_negotiable: Whether budget is negotiable
        tags: List of job tags
        applications: Application count information
        deadline: Application deadline
        author: Author information dict
        created_at: Creation timestamp
        updated_at: Last update timestamp
    """

    # Required fields
    id: str
    title: str
    slug: str
    url: str

    # Optional fields
    description: Optional[str] = None
    content: Optional[str] = None
    category: Optional[str] = None
    kind: Optional[str] = None
    status: Optional[str] = None
    budget: Optional[str] = None
    budget_value: Optional[float] = None
    is_volunteer: bool = False
    budget_negotiable: bool = False
    tags: List[str] = field(default_factory=list)
    applications: Optional[str] = None
    deadline: Optional[datetime] = None
    author: Optional[Dict[str, Any]] = None
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None

    # Category mapping
    CATEGORY_MAP = {
        "DEVELOPER": "Développement",
        "GRAPHISM": "Graphisme",
        "TEAM": "Équipe",
    }

    @classmethod
    def from_api_response(cls, data: Dict[str, Any], base_url: str = "https://creatorsarea.fr") -> Optional["Job"]:
        """
        Create a Job instance from API response data.

        Args:
            data: Raw API response data
            base_url: Base URL for constructing job URLs

        Returns:
            Job instance or None if parsing fails
        """
        try:
            job_id = data.get("_id")
            if not job_id:
                return None

            # Basic info
            title = data.get("title", "Untitled")
            slug = data.get("slug", job_id)
            url = f"{base_url}/offres/{slug}"

            # Content
            description = data.get("content", "")
            if description and len(description) > 800:
                description = description[:797] + "..."
            content = data.get("content", "")

            # Category
            kind = data.get("kind", "DEVELOPER")
            category = cls.CATEGORY_MAP.get(kind, kind)

            # Status
            status = data.get("status", "UNKNOWN")

            # Pricing
            pricing = data.get("pricing", {})
            budget_value = float(pricing.get("value", 0))
            is_volunteer = pricing.get("volunteer", False)
            budget_negotiable = pricing.get("negotiable", False)

            # Format budget
            budget = cls._format_budget(
                value=budget_value,
                negotiable=budget_negotiable,
                volunteer=is_volunteer,
            )

            # Tags
            tags = []
            for tag in data.get("_tags", []):
                tag_name = tag.get("name")
                if tag_name:
                    tags.append(tag_name)

            # Deadline
            deadline = None
            deadline_str = data.get("deadline")
            if deadline_str:
                try:
                    deadline = dateparser.parse(deadline_str)
                except Exception:
                    pass

            # Author
            author_data = data.get("author", {})
            author = {
                "id": author_data.get("_id"),
                "discord_id": author_data.get("discord_id"),
                "avatar": author_data.get("avatar"),
            } if author_data else None

            # Applications
            threads = data.get("threads", [])
            applications = f"{len(threads)} candidature(s)" if threads else None

            # Timestamps
            created_at = None
            created_str = data.get("createdAt")
            if created_str:
                try:
                    created_at = dateparser.parse(created_str)
                except Exception:
                    pass

            updated_at = None
            updated_str = data.get("updatedAt")
            if updated_str:
                try:
                    updated_at = dateparser.parse(updated_str)
                except Exception:
                    pass

            return cls(
                id=job_id,
                title=title,
                slug=slug,
                url=url,
                description=description,
                content=content,
                category=category,
                kind=kind,
                status=status,
                budget=budget,
                budget_value=budget_value,
                is_volunteer=is_volunteer,
                budget_negotiable=budget_negotiable,
                tags=tags,
                applications=applications,
                deadline=deadline,
                author=author,
                created_at=created_at or datetime.now(),
                updated_at=updated_at,
            )

        except Exception as e:
            print(f"Error parsing job data: {e}")
            return None

    @staticmethod
    def _format_budget(
        value: float,
        negotiable: bool = False,
        volunteer: bool = False,
        currency: str = "€"
    ) -> str:
        """
        Format budget value into a human-readable string.

        Args:
            value: Budget amount
            negotiable: Whether budget is negotiable
            volunteer: Whether this is volunteer work
            currency: Currency symbol

        Returns:
            Formatted budget string
        """
        if volunteer or value == 0:
            return "Bénévole 💚"

        budget_str = f"{value:,.0f} {currency}".replace(",", " ")

        if negotiable:
            budget_str += " (négociable)"

        return budget_str

    def to_dict(self) -> Dict[str, Any]:
        """
        Convert Job to dictionary format.

        Returns:
            Dictionary representation of the job
        """
        return {
            "id": self.id,
            "title": self.title,
            "slug": self.slug,
            "url": self.url,
            "description": self.description,
            "content": self.content,
            "category": self.category,
            "kind": self.kind,
            "status": self.status,
            "budget": self.budget,
            "budget_value": self.budget_value,
            "is_volunteer": self.is_volunteer,
            "budget_negotiable": self.budget_negotiable,
            "tags": self.tags,
            "applications": self.applications,
            "deadline": self.deadline.isoformat() if self.deadline else None,
            "author": self.author,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
        }

    def __repr__(self) -> str:
        """String representation."""
        return f"Job(id={self.id!r}, title={self.title!r}, budget={self.budget!r})"
