"""
Capa de servicio para lógica de negocio de relación entre partes y países
"""

import logging
from typing import Any, Dict, List, Optional, Tuple

from fastapi import HTTPException
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session

from .dto import PartCountryCreateDTO, PartCountryResponseDTO, PartCountryUpdateDTO
from .models import PartCountry

logger = logging.getLogger(__name__)


class PartCountryService:
    """Servicio para gestión de relaciones entre partes y países"""

    @staticmethod
    def get_all(
        db: Session,
        skip: int = 0,
        limit: int = 50,
        filters: Optional[Dict[str, Any]] = None,
    ) -> Tuple[List[PartCountry], int]:
        """Get all part-country relationships with pagination"""
        query = db.query(PartCountry)

        if filters:
            if filters.get("part_id"):
                query = query.filter(PartCountry.part_id == filters["part_id"])
            if filters.get("country_code"):
                query = query.filter(
                    PartCountry.country_code.ilike(f"%{filters['country_code']}%")
                )
            if filters.get("preference"):
                query = query.filter(PartCountry.preference == filters["preference"])

        total = query.count()
        part_countries = query.offset(skip).limit(limit).all()

        return part_countries, total

    @staticmethod
    def get_by_id(db: Session, part_country_id: int) -> Optional[PartCountry]:
        """Get part-country relationship by ID"""
        return db.query(PartCountry).filter(PartCountry.id == part_country_id).first()

    @staticmethod
    def get_by_part_id(db: Session, part_id: int) -> List[PartCountry]:
        """Get all countries for a specific part"""
        return db.query(PartCountry).filter(PartCountry.part_id == part_id).all()

    @staticmethod
    def get_by_part_and_country(db: Session, part_id: int, country_code: str) -> Optional[PartCountry]:
        """Get specific part-country relationship"""
        return db.query(PartCountry).filter(
            PartCountry.part_id == part_id,
            PartCountry.country_code == country_code
        ).first()

    @staticmethod
    def create(db: Session, part_country_data: PartCountryCreateDTO) -> PartCountry:
        """Create a new part-country relationship"""
        try:
            db_part_country = PartCountry(
                **part_country_data.model_dump(exclude_unset=True)
            )

            db.add(db_part_country)
            db.commit()
            db.refresh(db_part_country)

            return db_part_country

        except IntegrityError as e:
            db.rollback()
            logger.error(f"IntegrityError creating part-country relationship: {str(e)}")
            raise HTTPException(
                status_code=400,
                detail="Relationship already exists or invalid foreign key",
            )
        except Exception as e:
            db.rollback()
            logger.error(f"Error creating part-country relationship: {str(e)}")
            raise HTTPException(
                status_code=500,
                detail=f"Error creating relationship: {str(e)}",
            )

    @staticmethod
    def update(
        db: Session, part_country_id: int, part_country_data: PartCountryUpdateDTO
    ) -> Optional[PartCountry]:
        """Update part-country relationship"""
        try:
            db_part_country = db.query(PartCountry).filter(
                PartCountry.id == part_country_id
            ).first()

            if not db_part_country:
                return None

            update_data = part_country_data.model_dump(exclude_unset=True)
            for field, value in update_data.items():
                setattr(db_part_country, field, value)

            db.add(db_part_country)
            db.commit()
            db.refresh(db_part_country)

            return db_part_country

        except IntegrityError as e:
            db.rollback()
            logger.error(f"IntegrityError updating part-country relationship: {str(e)}")
            raise HTTPException(
                status_code=400,
                detail="Cannot update: constraint violation",
            )
        except Exception as e:
            db.rollback()
            logger.error(f"Error updating part-country relationship: {str(e)}")
            raise HTTPException(
                status_code=500,
                detail=f"Error updating relationship: {str(e)}",
            )

    @staticmethod
    def delete(db: Session, part_country_id: int) -> bool:
        """Delete part-country relationship"""
        try:
            db_part_country = db.query(PartCountry).filter(
                PartCountry.id == part_country_id
            ).first()

            if not db_part_country:
                return False

            db.delete(db_part_country)
            db.commit()

            return True

        except Exception as e:
            db.rollback()
            logger.error(f"Error deleting part-country relationship: {str(e)}")
            raise HTTPException(
                status_code=500,
                detail=f"Error deleting relationship: {str(e)}",
            )

    @staticmethod
    def bulk_create(db: Session, part_id: int, countries_data: List[PartCountryCreateDTO]) -> List[PartCountry]:
        """Create multiple part-country relationships for a part"""
        try:
            # Delete existing relationships for this part
            db.query(PartCountry).filter(PartCountry.part_id == part_id).delete()
            db.commit()

            # Create new relationships
            db_part_countries = []
            for country_data in countries_data:
                country_data.part_id = part_id
                db_part_country = PartCountry(
                    **country_data.model_dump(exclude_unset=True)
                )
                db_part_countries.append(db_part_country)

            db.add_all(db_part_countries)
            db.commit()

            for pc in db_part_countries:
                db.refresh(pc)

            return db_part_countries

        except Exception as e:
            db.rollback()
            logger.error(f"Error bulk creating part-country relationships: {str(e)}")
            raise HTTPException(
                status_code=500,
                detail=f"Error creating relationships: {str(e)}",
            )
