"""Application configuration settings using Pydantic BaseSettings."""

from pathlib import Path
from typing import Any

import albumentations as A
from pydantic_settings import BaseSettings

from src.models.image import ImageSet


class Settings(BaseSettings):
    """Application settings.

    Loads from environment variables and provides defaults.
    """

    # API Settings
    API_KEY: str | None = None

    # Paths
    BASE_DIR: Path = Path(__file__).parent.parent.parent

    # Data paths - can be overridden by environment variables
    IMAGE_PATH: Path = BASE_DIR / "data" / "images"
    LABEL_PATH: Path = BASE_DIR / "data" / "labels"
    FONT_PATH: Path = BASE_DIR / "data" / "fonts" / "LiberationSerif-Bold.ttf"

    # Logging
    LOG_FILE: str = "app.log"
    LOG_LEVEL: str = "INFO"
    LOG_FORMAT: str = "%(asctime)s - %(levelname)s - %(message)s"

    # Image sets configuration
    IMAGE_SETS: dict[str, ImageSet] = {
        "default": ImageSet(
            name="default",
            image_filename="billy.jpg",
            annotation_filename="billy.json",
        ),
        "HEStain": ImageSet(
            name="HEStain",
            image_filename="he_stained_tissue.jpg",
            annotation_filename=None,
        ),
        "ElasticTransform": ImageSet(
            name="ElasticTransform",
            image_filename="skull.jpg",
            annotation_filename="skull.json",
        ),
        "GridDistortion": ImageSet(
            name="GridDistortion",
            image_filename="skull.jpg",
            annotation_filename="skull.json",
        ),
        "GridElasticDeform": ImageSet(
            name="GridElasticDeform",
            image_filename="skull.jpg",
            annotation_filename="skull.json",
        ),
        "OpticalDistortion": ImageSet(
            name="OpticalDistortion",
            image_filename="skull.jpg",
            annotation_filename="skull.json",
        ),
        "XYMasking": ImageSet(
            name="XYMasking",
            image_filename="spectrogram.png",
            annotation_filename="spectrogram.json",
        ),
        "TimeMasking": ImageSet(
            name="TimeMasking",
            image_filename="spectrogram.png",
            annotation_filename="spectrogram.json",
        ),
        "FrequencyMasking": ImageSet(
            name="FrequencyMasking",
            image_filename="spectrogram.png",
            annotation_filename="spectrogram.json",
        ),
        "TimeReverse": ImageSet(
            name="TimeReverse",
            image_filename="spectrogram.png",
            annotation_filename="spectrogram.json",
        ),
        "Perspective": ImageSet(
            name="Perspective",
            image_filename="skull.jpg",
            annotation_filename="skull.json",
        ),
        "D4": ImageSet(
            name="D4",
            image_filename="road.jpg",
            annotation_filename="road.json",
        ),
        "Transpose": ImageSet(
            name="Transpose",
            image_filename="road.jpg",
            annotation_filename="road.json",
        ),
        "VerticalFlip": ImageSet(
            name="VerticalFlip",
            image_filename="road.jpg",
            annotation_filename="road.json",
        ),
        "SquareSymmetry": ImageSet(
            name="SquareSymmetry",
            image_filename="road.jpg",
            annotation_filename="road.json",
        ),
        "RandomRotate90": ImageSet(
            name="RandomRotate90",
            image_filename="road.jpg",
            annotation_filename="road.json",
        ),
        "ThinPlateSpline": ImageSet(
            name="ThinPlateSpline",
            image_filename="skull.jpg",
            annotation_filename="skull.json",
        ),
        "RandomFog": ImageSet(
            name="RandomFog",
            image_filename="driving.jpg",
            annotation_filename="driving.json",
        ),
        "RandomSunFlare": ImageSet(
            name="RandomSunFlare",
            image_filename="driving.jpg",
            annotation_filename="driving.json",
        ),
        "RandomShadow": ImageSet(
            name="RandomShadow",
            image_filename="driving.jpg",
            annotation_filename="driving.json",
        ),
        "RandomGravel": ImageSet(
            name="RandomGravel",
            image_filename="driving.jpg",
            annotation_filename="driving.json",
        ),
        "RandomRain": ImageSet(
            name="RandomRain",
            image_filename="driving.jpg",
            annotation_filename="driving.json",
        ),
        "RandomSnow": ImageSet(
            name="RandomSnow",
            image_filename="driving.jpg",
            annotation_filename="driving.json",
        ),
    }

    # Define ImageSets for Mosaic explicitly for clarity, reusing existing definitions
    # Note: We might need to adjust these if Mosaic specifically requires certain types/sizes later
    MOSAIC_INPUT_SETS: list[ImageSet] = [
        ImageSet(
            name="D4",
            image_filename="road.jpg",
            annotation_filename="road.json",
        ),
        ImageSet(
            name="ElasticTransform",
            image_filename="skull.jpg",
            annotation_filename="skull.json",
        ),
        ImageSet(
            name="RandomRain",
            image_filename="driving.jpg",
            annotation_filename="driving.json",
        ),
        ImageSet(
            name="XYMasking",
            image_filename="spectrogram.png",
            annotation_filename="spectrogram.json",
        ),
    ]

    REFERENCE_IMAGE_SETS: dict[str, list[ImageSet]] = {
        "default": [
            ImageSet(
                name="reference_parrot",
                image_filename="parrot.jpg",
                annotation_filename=None,  # Assuming parrot has no labels for now
            ),
        ],
        "Mosaic": MOSAIC_INPUT_SETS,
        # Add other transforms needing specific reference sets here if needed
        # e.g., "FDA": [ImageSet(name="style_transfer_ref", ...)]
    }

    model_config = {
        "env_file": ".env",
        "env_file_encoding": "utf-8",
        "case_sensitive": True,
    }

    MIXING_TRANSFORMS: set[Any] = {
        A.FDA,
        A.PixelDistributionAdaptation,
        A.HistogramMatching,
        A.Mosaic,
    }

    def get_image_set(self, transform_name: str) -> ImageSet:
        """Get the appropriate ImageSet based on transform name."""
        return self.IMAGE_SETS.get(transform_name, self.IMAGE_SETS["default"])

    def get_image_path(self, image_set: ImageSet) -> Path:
        """Get the image file path for an ImageSet."""
        return self.IMAGE_PATH / image_set.image_filename

    def get_reference_image_sets(self, transform_name: str | None = None) -> list[ImageSet]:
        """Get the list of reference/secondary ImageSets required for a transform."""
        # Return specific sets if defined for the transform, else return default.
        if transform_name and transform_name in self.REFERENCE_IMAGE_SETS:
            return self.REFERENCE_IMAGE_SETS[transform_name]
        return self.REFERENCE_IMAGE_SETS["default"]

    def get_annotation_path(self, image_set: ImageSet) -> Path | None:
        """Get the annotation file path for an ImageSet."""
        if image_set.annotation_filename:
            return self.LABEL_PATH / image_set.annotation_filename
        return None


# Create global settings instance
settings = Settings()
