"""Data contracts for the pipeline. Field names are binding per spec."""

from __future__ import annotations

import re
from datetime import datetime
from typing import Literal

from pydantic import BaseModel, Field, field_validator


def normalize_oe(raw: str) -> str:
    """Strip spaces, dots, dashes; uppercase."""
    return re.sub(r"[\s.\-/]", "", raw).upper()


# ---------------------------------------------------------------------------
# Post — normalised Facebook post
# ---------------------------------------------------------------------------
class Post(BaseModel):
    post_id: str
    group: str
    author_name: str
    author_profile_url: str
    text: str
    timestamp: datetime
    post_url: str


# ---------------------------------------------------------------------------
# Offer — normalised catalog offer (eBay / Allegro)
# ---------------------------------------------------------------------------
class Offer(BaseModel):
    offer_id: str
    platform: Literal["ebay", "allegro"]
    url: str
    title: str
    price: float | None = None
    currency: str = "PLN"
    qty: int = 1
    brand: str | None = None
    model: str | None = None
    category: str | None = None
    engine_code: str | None = None
    oe_numbers: list[str] = Field(default_factory=list)
    is_part: bool = True

    @field_validator("oe_numbers", mode="before")
    @classmethod
    def normalize_oe_numbers(cls, v: list[str]) -> list[str]:
        return [normalize_oe(n) for n in v if n.strip()]


# ---------------------------------------------------------------------------
# PartQuery — LLM extraction result
# ---------------------------------------------------------------------------
class PartQuery(BaseModel):
    is_part_request: bool
    raw_text: str
    brand: str | None = None
    model: str | None = None
    year: str | None = None
    category: str | None = None
    engine_code: str | None = None
    oe_numbers: list[str] = Field(default_factory=list)
    reason: str = ""

    @field_validator("oe_numbers", mode="before")
    @classmethod
    def normalize_oe_numbers(cls, v: list[str]) -> list[str]:
        from agent_samochodowy.matcher.normalize import is_plausible_oe

        result = []
        for n in v:
            if not n.strip():
                continue
            normalized = normalize_oe(n)
            if is_plausible_oe(normalized):
                result.append(normalized)
        return result


# ---------------------------------------------------------------------------
# MatchResult — matcher output
# ---------------------------------------------------------------------------
class MatchResult(BaseModel):
    confidence: float = Field(ge=0.0, le=1.0)
    method: Literal["oe", "engine_code", "atrybuty", "fuzzy", "brak"]
    offers: list[Offer] = Field(default_factory=list)
    matched: bool = False
