"""Base class for linkers."""

import warnings
from abc import ABC, abstractmethod

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


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

    left_id: str = Field(
        default="id", description="The unique ID field in the left data"
    )
    right_id: str = Field(
        default="id", description="The unique ID field in the right data"
    )

    @field_validator("left_id", "right_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 Linker(BaseModel, ABC):
    """A base class for linkers."""

    settings: LinkerSettings

    @abstractmethod
    def prepare(self, left: pl.DataFrame, right: pl.DataFrame) -> None:
        """Prepare the linker for linking."""
        return

    @abstractmethod
    def link(self, left: pl.DataFrame, right: pl.DataFrame) -> pl.DataFrame:
        """Link the left and right dataframes."""
        return
