"""
Proof-of-Comprehension solver — deterministic document parsing and question answering.

The solver extracts structured data from procedurally generated prose documents
using regex patterns, then answers multi-hop reasoning questions deterministically.
No LLM required — this is pure pattern matching on the challenge document.
"""

import re
import logging

log = logging.getLogger("litcoin")


def parse_document(doc, entity_names):
    """Parse the challenge document to extract entity data."""
    data = {}
    paragraphs = doc.split("\n\n")

    # Build alias → full name lookup
    alias_map = {}
    for name in entity_names:
        alias = name.split()[0]
        alias_map[alias] = name

    for name in entity_names:
        data[name] = {
            "revenue": 0, "patents": 0, "founded": 9999,
            "growth": -999.0, "employees": 0,
        }

    # Pass 1: Parse HOME paragraphs (one per entity)
    for para in paragraphs:
        if para.startswith("In a comparative"):
            continue

        owner = None
        for name in entity_names:
            if name in para:
                pos = para.find(name)
                if pos < 200 or owner is None:
                    owner = name
                    if pos < 100:
                        break
        if not owner:
            continue

        d = data[owner]

        # Revenue
        for pat in [
            r'total consolidated revenue to \$(\d[\d,]*)\s*million',
            r'\(total: \$(\d[\d,]*)\s*million\)',
            r'for a combined \$(\d[\d,]*)\s*million',
        ]:
            m = re.search(pat, para)
            if m:
                val = int(m.group(1).replace(",", ""))
                if val > d["revenue"]:
                    d["revenue"] = val

        if d["revenue"] == 0:
            base = 0
            sub = 0
            for pat in [r'(?:annual )?revenue of \$(\d[\d,]*)\s*million',
                        r'core revenue of \$(\d[\d,]*)\s*million',
                        r'revenue at \$(\d[\d,]*)\s*million']:
                m = re.search(pat, para)
                if m:
                    val = int(m.group(1).replace(",", ""))
                    if val > base:
                        base = val
            for pat in [r'additional \$(\d[\d,]*)\s*million',
                        r'supplemented by \$(\d[\d,]*)\s*million',
                        r'subsidiary contributions? of \$(\d[\d,]*)\s*million']:
                m = re.search(pat, para)
                if m:
                    val = int(m.group(1).replace(",", ""))
                    if val > sub:
                        sub = val
            total = base + sub if sub > 0 else base
            if total > d["revenue"]:
                d["revenue"] = total

        # Patents
        for pat in [r'(?:secured|holds?)\s+(\d+)\s+patents',
                    r'(\d+)\s+patents\s+(?:across|and)']:
            m = re.search(pat, para)
            if m:
                val = int(m.group(1))
                if val > d["patents"]:
                    d["patents"] = val

        # Founded
        for pat in [r'(?:was )?founded\s+(?:in\s+)?(\d{4})',
                    r'Founded\s+by\s+.*?\s+in\s+(\d{4})',
                    r'began\s+in\s+(\d{4})']:
            m = re.search(pat, para)
            if m:
                val = int(m.group(1))
                if 2000 <= val <= 2030 and val < d["founded"]:
                    d["founded"] = val

        # Growth
        for pat in [r'growth rate of\s+(-?\d+\.?\d*)%',
                    r'(-?\d+\.?\d*)%\s*(?:growth rate|year-over-year)',
                    r'representing\s+(-?\d+\.?\d*)%\s*year-over-year',
                    r"company's\s+(-?\d+\.?\d*)%\s*growth"]:
            m = re.search(pat, para)
            if m:
                val = float(m.group(1))
                if val > d["growth"]:
                    d["growth"] = val

        # Employees
        for pat in [r'(?:approximately\s+)?(\d[\d,]*)\s*people',
                    r'(\d[\d,]*)-person\s+enterprise',
                    r'employs\s+(?:approximately\s+)?(\d[\d,]*)\s*(?:staff|people)',
                    r'(\d[\d,]*)\s+staff']:
            m = re.search(pat, para)
            if m:
                val = int(m.group(1).replace(",", ""))
                if val > d["employees"]:
                    d["employees"] = val

    # Pass 2: Parse CROSS-REFERENCE paragraphs
    for para in paragraphs:
        if not para.startswith("In a comparative"):
            continue

        for m in re.finditer(r"(\w+)(?:'s|'s)\s+patent portfolio of\s+(\d+)", para):
            alias = m.group(1)
            val = int(m.group(2))
            if alias in alias_map:
                name = alias_map[alias]
                if val > data[name]["patents"]:
                    data[name]["patents"] = val

        for m in re.finditer(r"(\w+)(?:'s|'s)\s+(\d+)\s+patents", para):
            alias = m.group(1)
            val = int(m.group(2))
            if alias in alias_map:
                name = alias_map[alias]
                if val > data[name]["patents"]:
                    data[name]["patents"] = val

        m = re.search(r'(\w[\w\s]+?)\s+leads in employee count with\s+(\d[\d,]*)\s+staff', para)
        if m:
            ref = m.group(1).strip()
            val = int(m.group(2).replace(",", ""))
            for name in entity_names:
                if name == ref or name.endswith(ref):
                    if val > data[name]["employees"]:
                        data[name]["employees"] = val

        for m in re.finditer(r'(\d[\d,]*)\s+at\s+(\w[\w\s]*?)(?:\s+and\s|\s*\.)', para):
            ref = m.group(2).strip()
            val = int(m.group(1).replace(",", ""))
            for name in entity_names:
                if name == ref:
                    if val > data[name]["employees"]:
                        data[name]["employees"] = val
            if ref in alias_map:
                name = alias_map[ref]
                if val > data[name]["employees"]:
                    data[name]["employees"] = val

        for m in re.finditer(r'([\w][\w\s]+?)\s+reported\s+\$(\d[\d,]*)\s*million', para):
            ref = m.group(1).strip()
            val = int(m.group(2).replace(",", ""))
            for name in entity_names:
                if name == ref:
                    if val > data[name]["revenue"]:
                        data[name]["revenue"] = val

    return data


def answer_questions(data, questions):
    """Answer the 5 standard questions from parsed data."""
    answers = []
    for q in questions:
        ql = q.lower()
        if "revenue" in ql:
            winner = max(data.items(), key=lambda x: x[1]["revenue"])
        elif "patent" in ql:
            winner = max(data.items(), key=lambda x: x[1]["patents"])
        elif "founded" in ql or "earliest" in ql or "oldest" in ql:
            winner = min(data.items(), key=lambda x: x[1]["founded"])
        elif "growth" in ql:
            winner = max(data.items(), key=lambda x: x[1]["growth"])
        elif "employee" in ql:
            winner = max(data.items(), key=lambda x: x[1]["employees"])
        else:
            log.warning(f"Unknown question type: {q}")
            return None
        answers.append(winner[0])
    return answers


def compute_checksum(answers):
    """Sum of ASCII values of all answer characters, mod 9973."""
    return sum(ord(c) for c in "".join(answers)) % 9973


def solve(challenge):
    """
    Solve a challenge and return the artifact string.

    Args:
        challenge: dict from GET /v1/challenge with keys:
                   doc, questions, constraints, entities, solveInstructions

    Returns:
        artifact string (answers|checksum) or None on failure
    """
    try:
        doc = challenge.get("doc", "")
        questions = challenge.get("questions", [])
        entities = challenge.get("entities", [])

        data = parse_document(doc, entities)
        answers = answer_questions(data, questions)

        if not answers:
            log.error("Could not determine answers from parsed data")
            return None

        checksum = compute_checksum(answers)
        artifact = "|".join(answers) + f"|{checksum}"
        return artifact

    except Exception as e:
        log.error(f"Solve error: {e}")
        return None
