import os
import base64
from typing import Optional
from urllib.parse import quote

import httpx


def _config() -> dict:
    """Read config fresh each call so .env changes don't require a restart in dev."""
    return {
        "org": os.getenv("DEVOPS_ORG", ""),
        "project": os.getenv("DEVOPS_PROJECT", ""),
        "pat": os.getenv("DEVOPS_PAT", ""),
        "work_item_type": os.getenv("DEVOPS_WORK_ITEM_TYPE", "Task"),
    }


def _auth_header(pat: str) -> dict:
    """Azure DevOps Basic auth: base64 of an empty username + ':' + the PAT."""
    token = base64.b64encode(f":{pat}".encode()).decode()
    return {"Authorization": f"Basic {token}"}


async def create_work_item(
    title: str,
    description: str,
    assigned_to: Optional[str] = None,
) -> dict:
    """Create an Azure DevOps work item. Returns the full API response dict.

    Important fields in the response:
      - id:             work item ID (int)
      - _links.html.href: web URL for browser viewing
      - fields:         all field values as set by Azure DevOps
    """
    cfg = _config()
    if not (cfg["org"] and cfg["project"] and cfg["pat"]):
        raise RuntimeError(
            "Azure DevOps not configured — set DEVOPS_ORG, DEVOPS_PROJECT, DEVOPS_PAT in .env"
        )

    url = (
        f"https://dev.azure.com/{quote(cfg['org'])}/{quote(cfg['project'])}"
        f"/_apis/wit/workitems/${quote(cfg['work_item_type'])}?api-version=7.1"
    )

    # JSON Patch document — the only format Azure DevOps accepts for work item creation
    patch_doc = [
        {"op": "add", "path": "/fields/System.Title", "value": title},
        {"op": "add", "path": "/fields/System.Description", "value": description},
    ]
    if assigned_to:
        patch_doc.append(
            {"op": "add", "path": "/fields/System.AssignedTo", "value": assigned_to}
        )

    headers = {
        **_auth_header(cfg["pat"]),
        "Content-Type": "application/json-patch+json",
    }

    async with httpx.AsyncClient(timeout=30.0) as client:
        resp = await client.post(url, json=patch_doc, headers=headers)
        resp.raise_for_status()
        return resp.json()


async def get_work_item(work_item_id: int) -> dict:
    """Fetch a work item by ID — useful for status sync / polling."""
    cfg = _config()
    url = (
        f"https://dev.azure.com/{quote(cfg['org'])}/{quote(cfg['project'])}"
        f"/_apis/wit/workitems/{work_item_id}?api-version=7.1"
    )
    async with httpx.AsyncClient(timeout=30.0) as client:
        resp = await client.get(url, headers=_auth_header(cfg["pat"]))
        resp.raise_for_status()
        return resp.json()