"""Notion API integration — pages, databases, search."""

import os

import httpx

NOTION_API = "https://api.notion.com/v1"
NOTION_VERSION = "2022-06-28"


def _headers() -> dict:
    api_key = os.environ.get("NOTION_API_KEY")
    if not api_key:
        raise ValueError(
            "NOTION_API_KEY not set. Create an integration at "
            "https://www.notion.so/profile/integrations, copy the secret, "
            "then share your Notion pages with the integration."
        )
    return {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
        "Notion-Version": NOTION_VERSION,
    }


async def handler(params: dict) -> dict:
    """Handle Notion operations."""
    action = params["action"]
    headers = _headers()

    try:
        async with httpx.AsyncClient(timeout=30) as client:
            if action == "search":
                return await _search(client, headers, params)
            elif action == "create_page":
                return await _create_page(client, headers, params)
            elif action == "read_page":
                return await _read_page(client, headers, params)
            elif action == "update_page":
                return await _update_page(client, headers, params)
            elif action == "query_database":
                return await _query_database(client, headers, params)
            elif action == "create_database_entry":
                return await _create_database_entry(client, headers, params)
            else:
                return {"success": False, "message": f"Unknown action: {action}", "data": {}}
    except ValueError:
        raise
    except httpx.HTTPStatusError as e:
        error_body = e.response.text[:500]
        return {"success": False, "message": f"Notion API error ({e.response.status_code}): {error_body}", "data": {}}
    except Exception as e:
        return {"success": False, "message": f"Error: {e}", "data": {}}


async def _search(client: httpx.AsyncClient, headers: dict, params: dict) -> dict:
    query = params.get("query", "")
    body = {}
    if query:
        body["query"] = query

    resp = await client.post(f"{NOTION_API}/search", headers=headers, json=body)
    resp.raise_for_status()
    data = resp.json()

    results = []
    for item in data.get("results", [])[:20]:
        title = _extract_title(item)
        results.append({
            "id": item["id"],
            "type": item.get("object", ""),
            "title": title,
            "url": item.get("url", ""),
            "last_edited": item.get("last_edited_time", ""),
        })

    return {
        "success": True,
        "message": f"Found {len(results)} result(s)",
        "data": {"results": results},
    }


async def _create_page(client: httpx.AsyncClient, headers: dict, params: dict) -> dict:
    title = params.get("title")
    parent_page_id = params.get("parent_page_id")
    database_id = params.get("database_id")
    content = params.get("content", "")

    if not title:
        raise ValueError("'title' is required for create_page")
    if not parent_page_id and not database_id:
        raise ValueError("'parent_page_id' or 'database_id' is required for create_page")

    # Build parent
    if database_id:
        parent = {"database_id": database_id}
        properties = {"Name": {"title": [{"text": {"content": title}}]}}
    else:
        parent = {"page_id": parent_page_id}
        properties = {"title": {"title": [{"text": {"content": title}}]}}

    # Build content blocks
    children = []
    if content:
        for paragraph in content.split("\n\n"):
            paragraph = paragraph.strip()
            if paragraph:
                children.append({
                    "object": "block",
                    "type": "paragraph",
                    "paragraph": {
                        "rich_text": [{"type": "text", "text": {"content": paragraph}}]
                    },
                })

    body = {"parent": parent, "properties": properties}
    if children:
        body["children"] = children

    resp = await client.post(f"{NOTION_API}/pages", headers=headers, json=body)
    resp.raise_for_status()
    data = resp.json()

    return {
        "success": True,
        "message": f"Created page '{title}'",
        "data": {"id": data["id"], "url": data.get("url", "")},
    }


async def _read_page(client: httpx.AsyncClient, headers: dict, params: dict) -> dict:
    page_id = params.get("page_id")
    if not page_id:
        raise ValueError("'page_id' is required for read_page")

    # Fetch page metadata + blocks in parallel-ish (sequential for simplicity)
    resp = await client.get(f"{NOTION_API}/pages/{page_id}", headers=headers)
    resp.raise_for_status()
    page = resp.json()

    blocks_resp = await client.get(
        f"{NOTION_API}/blocks/{page_id}/children",
        headers=headers,
        params={"page_size": 100},
    )
    blocks_resp.raise_for_status()
    blocks_data = blocks_resp.json()

    # Extract text content from blocks
    content_parts = []
    for block in blocks_data.get("results", []):
        text = _extract_block_text(block)
        if text:
            content_parts.append(text)

    return {
        "success": True,
        "message": f"Read page {page_id}",
        "data": {
            "id": page["id"],
            "title": _extract_title(page),
            "url": page.get("url", ""),
            "last_edited": page.get("last_edited_time", ""),
            "content": "\n\n".join(content_parts),
            "properties": _simplify_properties(page.get("properties", {})),
        },
    }


async def _update_page(client: httpx.AsyncClient, headers: dict, params: dict) -> dict:
    page_id = params.get("page_id")
    properties = params.get("properties")
    if not page_id:
        raise ValueError("'page_id' is required for update_page")
    if not properties:
        raise ValueError("'properties' is required for update_page")

    resp = await client.patch(
        f"{NOTION_API}/pages/{page_id}",
        headers=headers,
        json={"properties": properties},
    )
    resp.raise_for_status()
    data = resp.json()

    return {
        "success": True,
        "message": f"Updated page {page_id}",
        "data": {"id": data["id"], "url": data.get("url", "")},
    }


async def _query_database(client: httpx.AsyncClient, headers: dict, params: dict) -> dict:
    database_id = params.get("database_id")
    if not database_id:
        raise ValueError("'database_id' is required for query_database")

    body = {}
    if params.get("filter"):
        body["filter"] = params["filter"]
    if params.get("sorts"):
        body["sorts"] = params["sorts"]

    resp = await client.post(
        f"{NOTION_API}/databases/{database_id}/query",
        headers=headers,
        json=body,
    )
    resp.raise_for_status()
    data = resp.json()

    entries = []
    for item in data.get("results", [])[:50]:
        entries.append({
            "id": item["id"],
            "url": item.get("url", ""),
            "properties": _simplify_properties(item.get("properties", {})),
        })

    return {
        "success": True,
        "message": f"Found {len(entries)} entries",
        "data": {"entries": entries, "has_more": data.get("has_more", False)},
    }


async def _create_database_entry(client: httpx.AsyncClient, headers: dict, params: dict) -> dict:
    database_id = params.get("database_id")
    properties = params.get("properties")
    if not database_id:
        raise ValueError("'database_id' is required for create_database_entry")
    if not properties:
        raise ValueError("'properties' is required for create_database_entry")

    resp = await client.post(
        f"{NOTION_API}/pages",
        headers=headers,
        json={"parent": {"database_id": database_id}, "properties": properties},
    )
    resp.raise_for_status()
    data = resp.json()

    return {
        "success": True,
        "message": "Database entry created",
        "data": {"id": data["id"], "url": data.get("url", "")},
    }


def _extract_title(item: dict) -> str:
    """Extract title from a Notion page or database object."""
    props = item.get("properties", {})
    for prop in props.values():
        if prop.get("type") == "title":
            title_arr = prop.get("title", [])
            if title_arr:
                return "".join(t.get("plain_text", "") for t in title_arr)
    # Fallback for database objects
    title_arr = item.get("title", [])
    if title_arr:
        return "".join(t.get("plain_text", "") for t in title_arr)
    return ""


def _extract_block_text(block: dict) -> str:
    """Extract plain text from a Notion block."""
    block_type = block.get("type", "")
    block_data = block.get(block_type, {})
    rich_text = block_data.get("rich_text", [])
    if rich_text:
        return "".join(t.get("plain_text", "") for t in rich_text)
    return ""


def _simplify_properties(properties: dict) -> dict:
    """Convert Notion property objects to simple key-value pairs."""
    result = {}
    for name, prop in properties.items():
        prop_type = prop.get("type", "")
        if prop_type == "title":
            result[name] = "".join(t.get("plain_text", "") for t in prop.get("title", []))
        elif prop_type == "rich_text":
            result[name] = "".join(t.get("plain_text", "") for t in prop.get("rich_text", []))
        elif prop_type == "number":
            result[name] = prop.get("number")
        elif prop_type == "select":
            sel = prop.get("select")
            result[name] = sel.get("name") if sel else None
        elif prop_type == "multi_select":
            result[name] = [s.get("name") for s in prop.get("multi_select", [])]
        elif prop_type == "date":
            d = prop.get("date")
            result[name] = d.get("start") if d else None
        elif prop_type == "checkbox":
            result[name] = prop.get("checkbox")
        elif prop_type == "url":
            result[name] = prop.get("url")
        elif prop_type == "email":
            result[name] = prop.get("email")
        elif prop_type == "status":
            s = prop.get("status")
            result[name] = s.get("name") if s else None
        else:
            result[name] = f"<{prop_type}>"
    return result
