"""
POS Configuration Repository using Repository Pattern
"""

from typing import List, Optional, Dict, Any
from uuid import UUID
from sqlalchemy import select, and_, or_
from sqlalchemy.ext.asyncio import AsyncSession
import structlog

from app.models.pos_config import POSConfiguration
from shared.database.repository import BaseRepository

logger = structlog.get_logger()


class POSConfigurationRepository(BaseRepository[POSConfiguration, dict, dict]):
    """Repository for POS configuration operations"""

    def __init__(self, session: AsyncSession):
        super().__init__(POSConfiguration, session)

    async def get_configurations_by_tenant(
        self,
        tenant_id: UUID,
        pos_system: Optional[str] = None,
        is_active: Optional[bool] = None,
        skip: int = 0,
        limit: int = 100
    ) -> List[POSConfiguration]:
        """Get POS configurations for a specific tenant with optional filters"""
        try:
            query = select(self.model).where(self.model.tenant_id == tenant_id)

            # Apply filters
            conditions = []
            if pos_system:
                conditions.append(self.model.pos_system == pos_system)
            if is_active is not None:
                conditions.append(self.model.is_active == is_active)

            if conditions:
                query = query.where(and_(*conditions))

            query = query.offset(skip).limit(limit).order_by(self.model.created_at.desc())

            result = await self.session.execute(query)
            return result.scalars().all()

        except Exception as e:
            logger.error("Failed to get configurations by tenant", error=str(e), tenant_id=tenant_id)
            raise

    async def count_configurations_by_tenant(
        self,
        tenant_id: UUID,
        pos_system: Optional[str] = None,
        is_active: Optional[bool] = None
    ) -> int:
        """Count POS configurations for a specific tenant with optional filters"""
        try:
            from sqlalchemy import func

            query = select(func.count(self.model.id)).where(self.model.tenant_id == tenant_id)

            # Apply filters
            conditions = []
            if pos_system:
                conditions.append(self.model.pos_system == pos_system)
            if is_active is not None:
                conditions.append(self.model.is_active == is_active)

            if conditions:
                query = query.where(and_(*conditions))

            result = await self.session.execute(query)
            count = result.scalar() or 0
            return count

        except Exception as e:
            logger.error("Failed to count configurations by tenant", error=str(e), tenant_id=tenant_id)
            raise

    async def get_by_pos_identifier(
        self,
        pos_system: str,
        identifier: str
    ) -> Optional[POSConfiguration]:
        """
        Get POS configuration by POS-specific identifier

        Args:
            pos_system: POS system name (square, toast, lightspeed)
            identifier: merchant_id, location_id, or other POS-specific ID

        Returns:
            POSConfiguration if found, None otherwise
        """
        try:
            query = select(self.model).where(
                and_(
                    self.model.pos_system == pos_system,
                    or_(
                        self.model.merchant_id == identifier,
                        self.model.location_id == identifier
                    ),
                    self.model.is_active == True
                )
            ).order_by(self.model.created_at.desc())

            result = await self.session.execute(query)
            return result.scalars().first()

        except Exception as e:
            logger.error("Failed to get config by POS identifier",
                        error=str(e),
                        pos_system=pos_system,
                        identifier=identifier)
            raise
