"""Fetch ``AGENTS.md`` (or ``CLAUDE.md`` fallback) from a GitHub repo.

Used by the reviewer to deterministically load repo conventions into context
without the model having to clone the repo and read the file itself.
"""

from __future__ import annotations

import logging

import httpx

logger = logging.getLogger(__name__)

# Cap the inlined content. AGENTS.md / CLAUDE.md is meant to be a short
# conventions doc; anything larger is probably accidental and would bloat
# every reviewer prompt.
_MAX_AGENTS_MD_BYTES = 64 * 1024

# Filenames tried in order of preference. AGENTS.md is the cross-tool standard;
# CLAUDE.md is the legacy Anthropic-specific filename still used by many repos.
_AGENT_DOC_FILENAMES = ("AGENTS.md", "CLAUDE.md")


async def fetch_agents_md(
    owner: str,
    repo: str,
    ref: str,
    *,
    token: str | None,
    timeout: float = 10.0,
) -> str | None:
    """Fetch ``AGENTS.md`` (or ``CLAUDE.md`` fallback) at ``ref`` from ``owner/repo``.

    Returns the raw file contents of the first matching file, or ``None`` if no
    file is found, a fetch fails, or the file exceeds the size cap. Only a 404
    (file absent) triggers fallback to the next filename; any other condition
    (oversize, HTTP error, unexpected status) returns ``None`` immediately so
    the reviewer does not enforce stale rules from a secondary file.
    """
    if not owner or not repo or not ref:
        return None

    headers = {
        "Accept": "application/vnd.github.raw",
        "X-GitHub-Api-Version": "2022-11-28",
    }
    if token:
        headers["Authorization"] = f"Bearer {token}"

    async with httpx.AsyncClient(timeout=timeout) as client:
        for filename in _AGENT_DOC_FILENAMES:
            url = f"https://api.github.com/repos/{owner}/{repo}/contents/{filename}"
            try:
                response = await client.get(url, headers=headers, params={"ref": ref})
            except httpx.HTTPError:
                logger.exception("Failed to fetch %s from %s/%s@%s", filename, owner, repo, ref)
                return None

            if response.status_code == 404:
                continue
            if response.status_code != 200:
                logger.warning(
                    "Unexpected status %s fetching %s from %s/%s@%s",
                    response.status_code,
                    filename,
                    owner,
                    repo,
                    ref,
                )
                return None

            content = response.text
            if len(content.encode("utf-8")) > _MAX_AGENTS_MD_BYTES:
                logger.info(
                    "%s in %s/%s@%s exceeds %d bytes; skipping inline",
                    filename,
                    owner,
                    repo,
                    ref,
                    _MAX_AGENTS_MD_BYTES,
                )
                return None

            logger.info(
                "Loaded %s (%d chars) from %s/%s@%s",
                filename,
                len(content),
                owner,
                repo,
                ref,
            )
            return content

    return None
