"""
createOS API client for session context.

Fetches task, epic, sprint, user story, and document data from the createOS Django API.

Environment Variables:
- CREATEOS_API_URL: Override API URL (optional)
- LW_ENV: Environment selection (local, staging, production) - default: local

API URL patterns by environment:
- Local: https://api.local.lightwave-media.ltd/v1/createOS
- Staging: https://api.staging.lightwave-media.ltd/v1/createOS
- Production: https://api.lightwave-media.ltd/v1/createOS

API Route Structure:
- /v1/createOS/*  - Task management (this client)
- /v1/auth/*      - Authentication
- /v1/public/*    - Public endpoints
- /v1/{tenant}/   - Tenant-specific (cineos, jes, etc.)
"""

import os
from typing import List, Literal, Optional

import httpx
from pydantic import ValidationError

from lightwave.context.context_models import (
    Document,
    Epic,
    ImplementationPlan,
    Sprint,
    Task,
    TaskContext,
    UserStory,
)

# API URL patterns by environment
API_URLS: dict[str, str] = {
    "local": "https://api.local.lightwave-media.ltd/v1/createOS",
    "staging": "https://api.staging.lightwave-media.ltd/v1/createOS",
    "production": "https://api.lightwave-media.ltd/v1/createOS",
}


def get_env() -> Literal["local", "staging", "production"]:
    """Get current environment from LW_ENV."""
    env = os.getenv("LW_ENV", "local").lower()
    if env == "staging":
        return "staging"
    if env in ("production", "prod"):
        return "production"
    return "local"


def get_api_url() -> str:
    """Get createOS API URL from environment."""
    # Explicit override takes precedence
    if override := os.getenv("CREATEOS_API_URL"):
        return override
    return API_URLS[get_env()]


def get_api_client() -> httpx.Client:
    """Get configured httpx client for createOS API."""
    return httpx.Client(
        base_url=get_api_url(),
        timeout=30.0,
        headers={"Content-Type": "application/json"},
    )


def fetch_task(task_id: str) -> Optional[Task]:
    """Fetch task by short ID or full UUID.

    Args:
        task_id: Task short ID (8-char hex) or full UUID

    Returns:
        Task model if found, None otherwise
    """
    try:
        with get_api_client() as client:
            # Try fetching by short_id first
            response = client.get(f"/api/createos/tasks/?short_id={task_id}")
            if response.status_code == 200:
                data = response.json()
                if data.get("count", 0) > 0:
                    task_data = data["results"][0]
                    return Task(**task_data)

            # Try fetching by full UUID
            response = client.get(f"/api/createos/tasks/{task_id}/")
            if response.status_code == 200:
                return Task(**response.json())

    except (httpx.HTTPError, ValidationError):
        pass

    return None


def fetch_epic(epic_id: str) -> Optional[Epic]:
    """Fetch epic by short ID or full UUID."""
    try:
        with get_api_client() as client:
            # Try short_id
            response = client.get(f"/api/createos/epics/?short_id={epic_id}")
            if response.status_code == 200:
                data = response.json()
                if data.get("count", 0) > 0:
                    return Epic(**data["results"][0])

            # Try full UUID
            response = client.get(f"/api/createos/epics/{epic_id}/")
            if response.status_code == 200:
                return Epic(**response.json())

    except (httpx.HTTPError, ValidationError):
        pass

    return None


def fetch_sprint(sprint_id: str) -> Optional[Sprint]:
    """Fetch sprint by short ID or full UUID."""
    try:
        with get_api_client() as client:
            # Try short_id
            response = client.get(f"/api/createos/sprints/?short_id={sprint_id}")
            if response.status_code == 200:
                data = response.json()
                if data.get("count", 0) > 0:
                    return Sprint(**data["results"][0])

            # Try full UUID
            response = client.get(f"/api/createos/sprints/{sprint_id}/")
            if response.status_code == 200:
                return Sprint(**response.json())

    except (httpx.HTTPError, ValidationError):
        pass

    return None


def fetch_user_story(story_id: str) -> Optional[UserStory]:
    """Fetch user story by short ID or full UUID."""
    try:
        with get_api_client() as client:
            # Try short_id
            response = client.get(f"/api/createos/user-stories/?short_id={story_id}")
            if response.status_code == 200:
                data = response.json()
                if data.get("count", 0) > 0:
                    return UserStory(**data["results"][0])

            # Try full UUID
            response = client.get(f"/api/createos/user-stories/{story_id}/")
            if response.status_code == 200:
                return UserStory(**response.json())

    except (httpx.HTTPError, ValidationError):
        pass

    return None


def fetch_document(doc_id: str) -> Optional[Document]:
    """Fetch document by short ID or full UUID."""
    try:
        with get_api_client() as client:
            # Try short_id
            response = client.get(f"/api/createos/documents/?short_id={doc_id}")
            if response.status_code == 200:
                data = response.json()
                if data.get("count", 0) > 0:
                    return Document(**data["results"][0])

            # Try full UUID
            response = client.get(f"/api/createos/documents/{doc_id}/")
            if response.status_code == 200:
                return Document(**response.json())

    except (httpx.HTTPError, ValidationError):
        pass

    return None


def fetch_implementation_plan(plan_id: str) -> Optional[ImplementationPlan]:
    """Fetch implementation plan by short ID or full UUID."""
    try:
        with get_api_client() as client:
            # Try short_id
            response = client.get(f"/api/createos/implementation-plans/?short_id={plan_id}")
            if response.status_code == 200:
                data = response.json()
                if data.get("count", 0) > 0:
                    return ImplementationPlan(**data["results"][0])

            # Try full UUID
            response = client.get(f"/api/createos/implementation-plans/{plan_id}/")
            if response.status_code == 200:
                return ImplementationPlan(**response.json())

    except (httpx.HTTPError, ValidationError):
        pass

    return None


def fetch_plans_for_task(task_id: str) -> List[ImplementationPlan]:
    """Fetch all implementation plans linked to a task."""
    try:
        with get_api_client() as client:
            response = client.get(f"/api/createos/implementation-plans/?task={task_id}")
            if response.status_code == 200:
                data = response.json()
                plans = []
                for plan_data in data.get("results", []):
                    try:
                        plans.append(ImplementationPlan(**plan_data))
                    except ValidationError:
                        continue
                return plans

    except httpx.HTTPError:
        pass

    return []


def fetch_task_context(task_id: str) -> Optional[TaskContext]:
    """Fetch complete task context including related entities.

    Args:
        task_id: Task short ID or full UUID

    Returns:
        TaskContext with task, epic, sprint, user stories, subtasks, and documents
    """
    task = fetch_task(task_id)
    if not task:
        return None

    # Fetch related epic
    epic = None
    if task.epic_id:
        epic = fetch_epic(task.epic_id)

    # Fetch related sprint
    sprint = None
    if task.sprint_id:
        sprint = fetch_sprint(task.sprint_id)

    # Fetch user stories (if task has user_story_id)
    user_stories: List[UserStory] = []
    if task.user_story_id:
        story = fetch_user_story(task.user_story_id)
        if story:
            user_stories.append(story)

    # Fetch subtasks (tasks where parent_task_id == this task)
    subtasks: List[Task] = []
    try:
        with get_api_client() as client:
            response = client.get(f"/api/createos/tasks/?parent_task={task.id}")
            if response.status_code == 200:
                data = response.json()
                for subtask_data in data.get("results", []):
                    try:
                        subtasks.append(Task(**subtask_data))
                    except ValidationError:
                        continue
    except httpx.HTTPError:
        pass

    # Fetch related documents (would need a task->document relation endpoint)
    documents: List[Document] = []
    # TODO: Implement when createOS API supports task->document queries

    return TaskContext(
        task=task,
        epic=epic,
        sprint=sprint,
        user_stories=user_stories,
        subtasks=subtasks,
        documents=documents,
    )
