"""
Capa de servicio para lógica de negocio de prevalidadores
"""

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 (
    PrevalidatorCreateDTO,
    PrevalidatorResponseDTO,
    PrevalidatorUpdateDTO,
)
from .models import Prevalidator

logger = logging.getLogger(__name__)


class PrevalidatorService:
    """Servicio para gestión de prevalidadores"""

    @staticmethod
    def get_all(
        db: Session,
        tenant_id: int,
        company_id: int,
        skip: int = 0,
        limit: int = 50,
        filters: Optional[Dict[str, Any]] = None,
    ) -> Tuple[List[Prevalidator], int]:
        """Get all prevalidators with pagination"""
        query = db.query(Prevalidator).filter(
            Prevalidator.tenant_id == tenant_id,
            Prevalidator.company_id == company_id
        )

        # Apply filters if provided
        if filters:
            if filters.get("code"):
                query = query.filter(
                    Prevalidator.code.ilike(f"%{filters['code']}%")
                )
            if filters.get("description"):
                query = query.filter(
                    Prevalidator.description.ilike(
                        f"%{filters['description']}%")
                )
            if filters.get("customs_prevalidator"):
                query = query.filter(
                    Prevalidator.customs_prevalidator.ilike(
                        f"%{filters['customs_prevalidator']}%"
                    )
                )

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

        return prevalidators, total

    @staticmethod
    def get_by_code(
        db: Session, code: str, tenant_id: int, company_id: int
    ) -> Optional[Prevalidator]:
        """Get prevalidator by code"""
        return db.query(Prevalidator).filter(
            Prevalidator.code == code,
            Prevalidator.tenant_id == tenant_id,
            Prevalidator.company_id == company_id
        ).first()

    @staticmethod
    def get_by_id(
        db: Session, prevalidator_id: int, tenant_id: int, company_id: int
    ) -> Optional[Prevalidator]:
        """Get prevalidator by ID"""
        return db.query(Prevalidator).filter(
            Prevalidator.id == prevalidator_id,
            Prevalidator.tenant_id == tenant_id,
            Prevalidator.company_id == company_id
        ).first()

    @staticmethod
    def create(
        db: Session,
        prevalidator_data: PrevalidatorCreateDTO,
        tenant_id: int,
        company_id: int
    ) -> Prevalidator:
        """Create a new prevalidator"""
        try:
            db_prevalidator = Prevalidator(
                **prevalidator_data.model_dump(exclude_unset=True),
                tenant_id=tenant_id,
                company_id=company_id
            )

            db.add(db_prevalidator)
            db.commit()
            db.refresh(db_prevalidator)

            return db_prevalidator

        except IntegrityError as e:
            db.rollback()
            logger.error(f"IntegrityError creating prevalidator: {str(e)}")
            raise HTTPException(
                status_code=400,
                detail="Prevalidator already exists",
            )
        except Exception as e:
            db.rollback()
            logger.error(f"Error creating prevalidator: {str(e)}")
            raise HTTPException(
                status_code=500, detail="Error creating prevalidator")

    @staticmethod
    def update(
        db: Session,
        prevalidator_id: int,
        tenant_id: int,
        prevalidator_data: PrevalidatorUpdateDTO,
        company_id: int
    ) -> Optional[Prevalidator]:
        """Update a prevalidator"""
        try:
            db_prevalidator = PrevalidatorService.get_by_id(
                db, prevalidator_id, tenant_id, company_id
            )
            if not db_prevalidator:
                return None

            for key, value in prevalidator_data.model_dump(exclude_unset=True).items():
                setattr(db_prevalidator, key, value)

            db.commit()
            db.refresh(db_prevalidator)

            return db_prevalidator

        except IntegrityError as e:
            db.rollback()
            logger.error(f"IntegrityError updating prevalidator: {str(e)}")
            raise HTTPException(
                status_code=400,
                detail="Error updating prevalidator",
            )
        except Exception as e:
            db.rollback()
            logger.error(f"Error updating prevalidator: {str(e)}")
            raise HTTPException(
                status_code=500, detail="Error updating prevalidator"
            )

    @staticmethod
    def delete(
        db: Session, prevalidator_id: int, tenant_id: int, company_id: int
    ) -> bool:
        """Delete a prevalidator"""
        try:
            db_prevalidator = PrevalidatorService.get_by_id(
                db, prevalidator_id, tenant_id, company_id
            )
            if not db_prevalidator:
                return False

            db.delete(db_prevalidator)
            db.commit()

            return True

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

    @staticmethod
    def get_by_customs(
        db: Session, customs: str, tenant_id: int, company_id: int
    ) -> List[Prevalidator]:
        """Get all prevalidators by customs"""
        return (
            db.query(Prevalidator)
            .filter(
                Prevalidator.customs_prevalidator == customs,
                Prevalidator.tenant_id == tenant_id,
                Prevalidator.company_id == company_id
            )
            .all()
        )
