"""
ACC (Autodesk Construction Cloud) Data Management API module.
Provides functions for navigating hubs, projects, folders, items, and versions.
"""

import requests
from .auth import get_user_token

BASE_URL = "https://developer.api.autodesk.com"


def _api_get(url, params=None):
    """Make authenticated GET request to APS API with user token."""
    token = get_user_token()
    if not token:
        raise RuntimeError("Not logged in. Use 3-legged OAuth2 flow first.")
    resp = requests.get(
        url,
        headers={"Authorization": f"Bearer {token}"},
        params=params,
    )
    if resp.status_code == 401:
        raise RuntimeError("Token expired. Please login again.")
    resp.raise_for_status()
    return resp.json()


def get_hubs():
    """
    List all ACC/BIM 360 hubs accessible by the user.

    Returns:
        list[dict]: [{id, name, type}, ...]
    """
    data = _api_get(f"{BASE_URL}/project/v1/hubs")
    return [
        {
            "id": h["id"],
            "name": h["attributes"]["name"],
            "type": h["attributes"].get("extension", {}).get("type", ""),
        }
        for h in data.get("data", [])
    ]


def get_projects(hub_id):
    """
    List projects in a hub (with pagination).

    Args:
        hub_id: Hub ID

    Returns:
        list[dict]: [{id, name, type, status}, ...]
    """
    all_projects = []
    url = f"{BASE_URL}/project/v1/hubs/{hub_id}/projects"
    while url:
        data = _api_get(url)
        for p in data.get("data", []):
            all_projects.append({
                "id": p["id"],
                "name": p["attributes"]["name"],
                "type": p["attributes"].get("extension", {}).get("type", ""),
                "status": p["attributes"].get("extension", {}).get("data", {}).get("projectType", ""),
            })
        url = data.get("links", {}).get("next", {})
        if isinstance(url, dict):
            url = url.get("href")
    return all_projects


def get_top_folders(hub_id, project_id):
    """
    List top-level folders in a project.

    Args:
        hub_id: Hub ID
        project_id: Project ID

    Returns:
        list[dict]: [{id, name, type}, ...]
    """
    data = _api_get(
        f"{BASE_URL}/project/v1/hubs/{hub_id}/projects/{project_id}/topFolders"
    )
    return [
        {
            "id": f["id"],
            "name": f["attributes"]["name"],
            "type": "folder",
        }
        for f in data.get("data", [])
    ]


def get_folder_contents(project_id, folder_id):
    """
    List contents of a folder (with pagination).

    Args:
        project_id: Project ID
        folder_id: Folder ID

    Returns:
        list[dict]: [{id, name, type, lastModified, ...}, ...]
    """
    all_items = []
    url = f"{BASE_URL}/data/v1/projects/{project_id}/folders/{folder_id}/contents"
    while url:
        data = _api_get(url)
        for item in data.get("data", []):
            attrs = item["attributes"]
            item_type = item["type"]
            entry = {
                "id": item["id"],
                "name": attrs.get("displayName") or attrs.get("name", ""),
                "type": "folder" if item_type == "folders" else "file",
                "lastModified": attrs.get("lastModifiedTime", ""),
                "createTime": attrs.get("createTime", ""),
            }
            if item_type == "items":
                entry["fileType"] = attrs.get("fileType", "")
                entry["extensionType"] = attrs.get("extension", {}).get("type", "")
            all_items.append(entry)
        url = data.get("links", {}).get("next", {})
        if isinstance(url, dict):
            url = url.get("href")
    all_items.sort(key=lambda x: (0 if x["type"] == "folder" else 1, x["name"].lower()))
    return all_items


def get_versions(project_id, item_id):
    """
    Get all versions of an item (latest first).

    Args:
        project_id: Project ID
        item_id: Item ID

    Returns:
        list[dict]: [{id, version, name, urn, ...}, ...]
    """
    data = _api_get(
        f"{BASE_URL}/data/v1/projects/{project_id}/items/{item_id}/versions"
    )
    versions = []
    for v in data.get("data", []):
        attrs = v["attributes"]
        deriv = v.get("relationships", {}).get("derivatives", {}).get("data", {})
        versions.append({
            "id": v["id"],
            "version": attrs.get("versionNumber", 0),
            "name": attrs.get("name", ""),
            "lastModified": attrs.get("lastModifiedTime", ""),
            "createTime": attrs.get("createTime", ""),
            "fileType": attrs.get("fileType", ""),
            "urn": deriv.get("id", ""),
        })
    versions.sort(key=lambda x: x["version"], reverse=True)
    return versions


def get_item_tip(project_id, item_id):
    """
    Get the latest version (tip) of an item, including its viewer URN.

    Args:
        project_id: Project ID
        item_id: Item ID

    Returns:
        dict: {name, version, fileType, urn, lastModified}
    """
    data = _api_get(
        f"{BASE_URL}/data/v1/projects/{project_id}/items/{item_id}/tip"
    )
    attrs = data.get("data", {}).get("attributes", {})
    deriv = data.get("data", {}).get("relationships", {}).get("derivatives", {}).get("data", {})
    return {
        "name": attrs.get("name", ""),
        "version": attrs.get("versionNumber", 0),
        "fileType": attrs.get("fileType", ""),
        "urn": deriv.get("id", ""),
        "lastModified": attrs.get("lastModifiedTime", ""),
    }


def get_user_profile():
    """
    Get the logged-in user's profile.

    Returns:
        dict: {name, email} or None if not logged in
    """
    token = get_user_token()
    if not token:
        return None
    try:
        resp = requests.get(
            f"{BASE_URL}/userprofile/v1/users/@me",
            headers={"Authorization": f"Bearer {token}"},
        )
        if resp.status_code == 200:
            profile = resp.json()
            return {
                "name": f"{profile.get('firstName', '')} {profile.get('lastName', '')}".strip(),
                "email": profile.get("emailId", ""),
            }
    except Exception:
        pass
    return None
