"""Base class for deduplication methodologies."""

import warnings
from abc import ABC, abstractmethod

import polars as pl
from pydantic import BaseModel, Field, ValidationInfo, field_validator


class DeduperSettings(BaseModel):
    """A data class to enforce basic settings dictionary shapes."""

    id: str = Field(default="id", description="A unique ID field in the data to dedupe")

    @field_validator("id")
    @classmethod
    def _id_for_mb(cls, v: str, info: ValidationInfo) -> str:
        enforce = "id"
        if v != enforce:
            warnings.warn(
                f"For offline deduplication, {info.field_name} can be any field. \n\n"
                "When deduplicating to write back to the Company Matching "
                f"Framework database, the ID must be '{enforce}', generated by "
                "matchbox queries.",
                stacklevel=3,
            )
        return v


class Deduper(BaseModel, ABC):
    """A base class for dedupers."""

    settings: DeduperSettings

    @abstractmethod
    def prepare(self, data: pl.DataFrame) -> None:
        """Prepare the deduper for deduplication."""
        return

    @abstractmethod
    def dedupe(self, data: pl.DataFrame) -> pl.DataFrame:
        """Deduplicate the dataframe."""
        return
