"""Digital Menu Catalog repositories — Phase 12.1."""
from __future__ import annotations

from uuid import UUID

from sqlalchemy import select

from app.models.catalog import (
    Allergen,
    AvailabilityWindow,
    MenuItemAllergen,
    MenuItemModifier,
    MenuLocalization,
    MenuMediaRef,
    ModifierGroup,
    ModifierOption,
)
from app.models.types import AvailabilityScope, LocalizationTarget
from app.repositories.base import TenantBaseRepository


class AllergenRepository(TenantBaseRepository[Allergen]):
    model = Allergen

    async def get_by_code(
        self, tenant_id: UUID, venue_id: UUID, code: str
    ) -> Allergen | None:
        stmt = select(Allergen).where(
            Allergen.tenant_id == tenant_id,
            Allergen.venue_id == venue_id,
            Allergen.code == code,
            Allergen.is_deleted.is_(False),
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()


class ModifierGroupRepository(TenantBaseRepository[ModifierGroup]):
    model = ModifierGroup

    async def get_by_code(
        self, tenant_id: UUID, venue_id: UUID, code: str
    ) -> ModifierGroup | None:
        stmt = select(ModifierGroup).where(
            ModifierGroup.tenant_id == tenant_id,
            ModifierGroup.venue_id == venue_id,
            ModifierGroup.code == code,
            ModifierGroup.is_deleted.is_(False),
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()


class ModifierOptionRepository(TenantBaseRepository[ModifierOption]):
    model = ModifierOption

    async def get_by_code(
        self, tenant_id: UUID, modifier_group_id: UUID, code: str
    ) -> ModifierOption | None:
        stmt = select(ModifierOption).where(
            ModifierOption.tenant_id == tenant_id,
            ModifierOption.modifier_group_id == modifier_group_id,
            ModifierOption.code == code,
            ModifierOption.is_deleted.is_(False),
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()


class MenuItemModifierRepository(TenantBaseRepository[MenuItemModifier]):
    model = MenuItemModifier

    async def get_link(
        self, tenant_id: UUID, menu_item_id: UUID, modifier_group_id: UUID
    ) -> MenuItemModifier | None:
        stmt = select(MenuItemModifier).where(
            MenuItemModifier.tenant_id == tenant_id,
            MenuItemModifier.menu_item_id == menu_item_id,
            MenuItemModifier.modifier_group_id == modifier_group_id,
            MenuItemModifier.is_deleted.is_(False),
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()


class MenuItemAllergenRepository(TenantBaseRepository[MenuItemAllergen]):
    model = MenuItemAllergen

    async def get_link(
        self, tenant_id: UUID, menu_item_id: UUID, allergen_id: UUID
    ) -> MenuItemAllergen | None:
        stmt = select(MenuItemAllergen).where(
            MenuItemAllergen.tenant_id == tenant_id,
            MenuItemAllergen.menu_item_id == menu_item_id,
            MenuItemAllergen.allergen_id == allergen_id,
            MenuItemAllergen.is_deleted.is_(False),
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()


class AvailabilityWindowRepository(TenantBaseRepository[AvailabilityWindow]):
    model = AvailabilityWindow

    async def get_by_code(
        self,
        tenant_id: UUID,
        venue_id: UUID,
        scope: AvailabilityScope,
        target_id: UUID,
        code: str,
    ) -> AvailabilityWindow | None:
        stmt = select(AvailabilityWindow).where(
            AvailabilityWindow.tenant_id == tenant_id,
            AvailabilityWindow.venue_id == venue_id,
            AvailabilityWindow.scope == scope,
            AvailabilityWindow.target_id == target_id,
            AvailabilityWindow.code == code,
            AvailabilityWindow.is_deleted.is_(False),
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()


class MenuMediaRefRepository(TenantBaseRepository[MenuMediaRef]):
    model = MenuMediaRef


class MenuLocalizationRepository(TenantBaseRepository[MenuLocalization]):
    model = MenuLocalization

    async def get_locale(
        self,
        tenant_id: UUID,
        target_type: LocalizationTarget,
        target_id: UUID,
        locale: str,
    ) -> MenuLocalization | None:
        stmt = select(MenuLocalization).where(
            MenuLocalization.tenant_id == tenant_id,
            MenuLocalization.target_type == target_type,
            MenuLocalization.target_id == target_id,
            MenuLocalization.locale == locale,
            MenuLocalization.is_deleted.is_(False),
        )
        result = await self.session.execute(stmt)
        return result.scalar_one_or_none()
