"""Result types for the two-flow extractor.

`VisualTable` is one table as identified by looking at the page (the
authoritative count and identity). `CamelotTable` is one cell grid pulled
by Camelot, carrying its classifier verdict as metadata only — the verdict
never drops a candidate here, because identity is the visual flow's job.
`DualResult` holds both lists for one document, unmatched.
"""

from __future__ import annotations

from typing import List, Optional, Tuple

from pydantic import BaseModel, Field

from quber.agents.classifier import ClassifierResult
from quber.core.extractors.camelot.acquire import CamelotCandidate


class VisualTable(BaseModel):
    """A table the visual flow found on a page, with its full-anatomy box."""

    page: int = Field(ge=1, description="1-indexed page the table sits on")
    ordinal: int = Field(ge=1, description="1-based reading-order position within the page")
    title: str = Field(default="", description="Visible caption, else a one-line column summary")
    region: Tuple[float, float, float, float] = Field(
        description="Boundary box, normalized 0..1 with the page top-left as origin (x1, y1, x2, y2)"
    )
    tightened: bool = Field(
        description="True if the box was snapped to the text layer; False if the coarse grid cell was kept"
    )


class CamelotTable(BaseModel):
    """A Camelot cell grid plus its is-table verdict (metadata, not a gate)."""

    candidate: CamelotCandidate = Field(description="Raw Camelot output: cells, markdown, bbox, accuracy")
    classification: Optional[ClassifierResult] = Field(
        default=None,
        description="Classifier's is_table verdict, kept for later cross-reference; it does not drop the candidate",
    )


class DualResult(BaseModel):
    """Both flows' output for one document, side by side and unmatched."""

    source: str = Field(description="Path of the source PDF")
    visual: List[VisualTable] = Field(
        default_factory=list, description="Tables identified by the visual flow"
    )
    camelot: List[CamelotTable] = Field(default_factory=list, description="Cell grids extracted by Camelot")

    def visual_count_by_page(self) -> dict[int, int]:
        counts: dict[int, int] = {}
        for t in self.visual:
            counts[t.page] = counts.get(t.page, 0) + 1
        return counts

    def camelot_count_by_page(self) -> dict[int, int]:
        counts: dict[int, int] = {}
        for t in self.camelot:
            counts[t.candidate.page] = counts.get(t.candidate.page, 0) + 1
        return counts
