from __future__ import annotations

import re
from typing import List

from pdfminer.high_level import extract_text

from ..extract_ids import extract_ids
from ..types import ReferenceInput
from ..util import collapse_whitespace, stable_hash


HEADING_RE = re.compile(r"\n\s*(references|bibliography|works cited)\s*\n", re.IGNORECASE)
MARKER_RE = re.compile(r"^\s*(\[\d+\]|\d+\.|\d+\))\s+")


def _split_references(block: str) -> list[str]:
    lines = [line.rstrip() for line in block.splitlines()]
    refs: list[str] = []
    current: list[str] = []

    for line in lines:
        stripped = line.strip()
        if not stripped:
            if current:
                refs.append(collapse_whitespace(" ".join(current)))
                current = []
            continue
        marker_match = MARKER_RE.match(stripped)
        if marker_match:
            if current:
                refs.append(collapse_whitespace(" ".join(current)))
                current = []
            stripped = MARKER_RE.sub("", stripped)
        current.append(stripped)

    if current:
        refs.append(collapse_whitespace(" ".join(current)))

    return [ref for ref in refs if ref]


def ingest_pdf(path: str, min_text_chars: int = 500) -> List[ReferenceInput]:
    text = extract_text(path)
    if len(text.strip()) < min_text_chars:
        raw = "PDF appears scanned or has no extractable text."
        return [
            ReferenceInput(
                source_path=path,
                source_kind="pdf",
                ref_id=f"ref_{stable_hash(raw)}",
                raw=raw,
                fields={"error": raw},
                parse_confidence="LOW",
            )
        ]

    matches = list(HEADING_RE.finditer(text))
    if not matches:
        return []

    start_idx = None
    text_len = len(text)
    for match in matches:
        if match.start() >= int(text_len * 0.5):
            start_idx = match.end()
            break
    if start_idx is None:
        start_idx = matches[-1].end()

    ref_block = text[start_idx:]
    refs = _split_references(ref_block)

    results: List[ReferenceInput] = []
    for ref in refs:
        ids = extract_ids(ref)
        fields = {"raw": ref, **ids}
        results.append(
            ReferenceInput(
                source_path=path,
                source_kind="pdf",
                ref_id=f"ref_{stable_hash(ref)}",
                raw=ref,
                fields=fields,
                parse_confidence="LOW" if not ids else "MED",
            )
        )
    return results
