import logging
from typing import Dict, List, Optional

from sqlalchemy.orm import Session

from src.apps.match.enums import Source
from src.apps.wine.wine.models.wine import Wine, WineDb, WineKeyword
from src.apps.wine.producer.models.producer import Producer
logger = logging.getLogger(__name__)


class SimpleModel:
    id: str
    label: str


class WineService:
    # def __init__(self, db_session):
    #     self.db = db_session

    def is_wine_db_exists(db: Session, wine_db_id: int) -> bool:
        try:
            # Replace with actual SQLAlchemy query
            result = db.query(WineDb).filter(WineDb.id == wine_db_id, WineDb.status == "ACTIVE").count()
            return result > 0
        except Exception as e:
            logger.error(f"is_wine_db_exists error: {e}")
            return False

    def get_wine_properties_for_match_validation(db: Session, wine_id: str, wine_db_id: str) -> List[str]:
        try:
            wine = (
                db.query(
                    WineDb.color,
                    WineDb.type,
                    WineDb.sweetness,
                    WineDb.variety,
                    WineDb.note,
                    WineDb.name,
                    WineDb.wine_country,
                    WineDb.wine_region,
                    WineDb.wine_location,
                    WineDb.wine_locale,
                    WineDb.wine_site,
                    Producer.name_show,
                    WineKeyword.pattern,
                    Wine.maturity,
                    Wine.mongo_id,
                )
                .join(WineDb.producer)
                .outerjoin(WineDb.wine_keyword)
                .join(Wine)
                .filter(Wine.id == wine_id)
                .first()
            )

            if not wine:
                wine = (
                    db.query(
                        WineDb.color,
                        WineDb.type,
                        WineDb.sweetness,
                        WineDb.variety,
                        WineDb.note,
                        WineDb.name,
                        WineDb.wine_country,
                        WineDb.wine_region,
                        WineDb.wine_location,
                        WineDb.wine_locale,
                        WineDb.wine_site,
                        Producer.name_show,
                        WineKeyword.pattern,
                    )
                    .join(WineDb.producer)
                    .outerjoin(WineDb.wine_keyword)
                    .filter(WineDb.id == wine_db_id)
                    .first()
                )

                if wine:
                    wine = list(wine)
                    wine += ["", ""]  # placeholders for maturity, mongo_id
            return list(wine) if wine else []
        except Exception as e:
            logger.error(f"get_wine_properties_for_match_validation error: {e}")
            return []

    def get_wines_with_description(db: Session, ids: List[str]) -> List[SimpleModel]:
        if not ids:
            return []
        try:
            wines = (
                db.query(WineDb.id, WineDb.name, WineDb.color, Producer.name_show)
                .join(WineDb.producer)
                .filter(WineDb.id.in_(ids))
                .all()
            )

            result = []
            for w in wines:
                label = f"{w[3]} {w[1]} ({w[2]})"
                result.append(SimpleModel(id=w[0], label=label))
            return result
        except Exception as e:
            logger.error(f"get_wines_with_description error: {e}")
            return []

    def save_keywords(self, db: Session, keywords: List[Dict], source: Source) -> List:
        saved = []
        for data in keywords:
            wine_db_id = data.get("wineDbId")
            exists = db.query(WineKeyword).join(WineDb).filter(WineDb.id == wine_db_id).count()
            if not exists:
                wine_db = db.query(WineDb).filter(WineDb.id == wine_db_id).first()
                if wine_db:
                    keyword = self.save_keyword(
                        db=db,
                        wine_db=wine_db,
                        producer_keyword=data.get("producerKeyword"),
                        base_keyword=data.get("baseKeyword"),
                        appellation_keyword=data.get("appellationKeyword"),
                        color_keyword=data.get("colorKeyword"),
                        common_modifiers_keyword=data.get("commonModifiersKeyword"),
                        modifiers_keyword=data.get("modifiersKeyword"),
                        custom_not_keyword=None,
                        global_not_keyword=data.get("globalNotKeyword"),
                        source=source,
                    )
                    if keyword:
                        saved.append(keyword)
        return saved

    def save_keyword(
        self,
        db: Session,
        wine_db,
        producer_keyword: str,
        base_keyword: str,
        appellation_keyword: str,
        color_keyword: str,
        common_modifiers_keyword: str,
        modifiers_keyword: str,
        custom_not_keyword: Optional[str],
        global_not_keyword: str,
        source: Source,
    ):
        try:
            pattern = self._generate_pattern(
                producer_keyword,
                base_keyword,
                appellation_keyword,
                color_keyword,
                common_modifiers_keyword,
                modifiers_keyword,
                custom_not_keyword,
                global_not_keyword,
            )

            wine_keyword = WineKeyword(
                wine_db=wine_db,
                producer_keyword=producer_keyword,
                base_keyword=base_keyword,
                appellation_keyword=appellation_keyword,
                color_keyword=color_keyword,
                common_modifiers_keyword=common_modifiers_keyword,
                modifiers_keyword=modifiers_keyword,
                custom_not_keyword=custom_not_keyword,
                global_not_keyword=global_not_keyword,
                pattern=pattern,
                source=source,
            )
            db.add(wine_keyword)
            db.commit()
            return wine_keyword
        except Exception as e:
            logger.error(f"Failed to save WineKeyword: {e}")
            db.rollback()
            return None

    def _generate_pattern(self, *args) -> str:
        # This mimics WineKeywordUtils.joinPattern
        return " ".join(filter(None, args))
