"""
APS Model Derivative / Viewer API module.
Provides functions to query model metadata, properties, phases, and thumbnails.
"""

import requests
from .auth import get_2legged_token, get_user_token

BASE_URL = "https://developer.api.autodesk.com"


def _get_token(use_user_token=False):
    """Get appropriate token based on context."""
    if use_user_token:
        token = get_user_token()
        if not token:
            raise RuntimeError("Not logged in (3-legged token required)")
        return token
    return get_2legged_token()


def get_metadata(urn, use_user_token=False):
    """
    List views/GUIDs in a model.

    Args:
        urn: Base64-encoded model URN
        use_user_token: Use 3-legged token instead of 2-legged

    Returns:
        dict: Metadata response from APS
    """
    token = _get_token(use_user_token)
    resp = requests.get(
        f"{BASE_URL}/modelderivative/v2/designdata/{urn}/metadata",
        headers={"Authorization": f"Bearer {token}"},
    )
    resp.raise_for_status()
    return resp.json()


def get_properties(urn, guid, use_user_token=False):
    """
    Get all element properties for a view.

    Args:
        urn: Base64-encoded model URN
        guid: View GUID from metadata
        use_user_token: Use 3-legged token

    Returns:
        dict: Properties response
    """
    token = _get_token(use_user_token)
    resp = requests.get(
        f"{BASE_URL}/modelderivative/v2/designdata/{urn}/metadata/{guid}/properties",
        headers={"Authorization": f"Bearer {token}"},
        params={"forceget": "true"},
    )
    resp.raise_for_status()
    return resp.json()


def get_tree(urn, guid, use_user_token=False):
    """
    Get object tree hierarchy for a view.

    Args:
        urn: Base64-encoded model URN
        guid: View GUID
        use_user_token: Use 3-legged token

    Returns:
        dict: Tree hierarchy response
    """
    token = _get_token(use_user_token)
    resp = requests.get(
        f"{BASE_URL}/modelderivative/v2/designdata/{urn}/metadata/{guid}",
        headers={"Authorization": f"Bearer {token}"},
        params={"forceget": "true"},
    )
    resp.raise_for_status()
    return resp.json()


def get_thumbnail(urn, width=400, height=400, use_user_token=False):
    """
    Get model thumbnail image.

    Args:
        urn: Base64-encoded model URN
        width: Thumbnail width
        height: Thumbnail height
        use_user_token: Use 3-legged token

    Returns:
        bytes: PNG image data
    """
    token = _get_token(use_user_token)
    resp = requests.get(
        f"{BASE_URL}/modelderivative/v2/designdata/{urn}/thumbnail",
        headers={"Authorization": f"Bearer {token}"},
        params={"width": width, "height": height},
    )
    resp.raise_for_status()
    return resp.content


def get_manifest(urn, use_user_token=False):
    """
    Get translation manifest (status, derivatives).

    Args:
        urn: Base64-encoded model URN
        use_user_token: Use 3-legged token

    Returns:
        dict: Manifest response
    """
    token = _get_token(use_user_token)
    resp = requests.get(
        f"{BASE_URL}/modelderivative/v2/designdata/{urn}/manifest",
        headers={"Authorization": f"Bearer {token}"},
    )
    resp.raise_for_status()
    return resp.json()


def get_phases(urn, guid, use_user_token=False):
    """
    Extract phase/construction stage data per element.

    Args:
        urn: Base64-encoded model URN
        guid: View GUID
        use_user_token: Use 3-legged token

    Returns:
        dict: {phases, phaseElements, elements, totalElements, phasedElements}
    """
    data = get_properties(urn, guid, use_user_token)
    collection = data.get("data", {}).get("collection", [])

    phases = {}
    elements = {}
    phase_names = set()

    for elem in collection:
        db_id = elem.get("objectid")
        elem_name = elem.get("name", "")
        props = elem.get("properties", {})

        phase_created = None
        phase_demolished = None
        category = ""

        phasing = props.get("Phasing", {})
        if isinstance(phasing, dict):
            phase_created = phasing.get("Phase Created")
            phase_demolished = phasing.get("Phase Demolished")

        cat_data = props.get("__category__", {})
        if isinstance(cat_data, dict):
            category = cat_data.get("__category__", "")

        if phase_created:
            phase_names.add(phase_created)
            if phase_created not in phases:
                phases[phase_created] = []
            phases[phase_created].append(db_id)
            elements[str(db_id)] = {
                "name": elem_name,
                "phaseCreated": phase_created,
                "phaseDemolished": phase_demolished,
                "category": category,
            }

    sorted_phases = sorted(phase_names)
    return {
        "phases": sorted_phases,
        "phaseElements": phases,
        "elements": elements,
        "totalElements": len(collection),
        "phasedElements": len(elements),
    }
