"""
Concatenated match strategy - finds value by concatenating adjacent tokens.
"""

from .base import BaseMatchStrategy
from ..models import TokenLike, Match
from ..token_index import TokenIndex
from ..context import find_context_keywords
from ..utils import WHITESPACE_PATTERN, tokens_on_same_line


class ConcatenatedMatcher(BaseMatchStrategy):
    """Find value by concatenating adjacent tokens."""

    def find_matches(
        self,
        tokens: list[TokenLike],
        value: str,
        field_name: str,
        token_index: TokenIndex | None = None
    ) -> list[Match]:
        """Find concatenated matches."""
        matches = []
        value_clean = WHITESPACE_PATTERN.sub('', value)

        # Sort tokens by position (top-to-bottom, left-to-right)
        sorted_tokens = sorted(tokens, key=lambda t: (t.bbox[1], t.bbox[0]))

        for i, start_token in enumerate(sorted_tokens):
            # Try to build the value by concatenating nearby tokens
            concat_text = start_token.text.strip()
            concat_bbox = list(start_token.bbox)
            used_tokens = [start_token]

            for j in range(i + 1, min(i + 5, len(sorted_tokens))):  # Max 5 tokens
                next_token = sorted_tokens[j]

                # Check if tokens are on the same line (y overlap)
                if not tokens_on_same_line(start_token, next_token):
                    break

                # Check horizontal proximity
                if next_token.bbox[0] - concat_bbox[2] > 50:  # Max 50px gap
                    break

                concat_text += next_token.text.strip()
                used_tokens.append(next_token)

                # Update bounding box
                concat_bbox[0] = min(concat_bbox[0], next_token.bbox[0])
                concat_bbox[1] = min(concat_bbox[1], next_token.bbox[1])
                concat_bbox[2] = max(concat_bbox[2], next_token.bbox[2])
                concat_bbox[3] = max(concat_bbox[3], next_token.bbox[3])

                # Check for match
                concat_clean = WHITESPACE_PATTERN.sub('', concat_text)
                if concat_clean == value_clean:
                    context_keywords, context_boost = find_context_keywords(
                        tokens, start_token, field_name, self.context_radius, token_index
                    )

                    matches.append(Match(
                        field=field_name,
                        value=value,
                        bbox=tuple(concat_bbox),
                        page_no=start_token.page_no,
                        score=min(1.0, 0.85 + context_boost),  # Slightly lower base score
                        matched_text=concat_text,
                        context_keywords=context_keywords
                    ))
                    break

        return matches
