"""
Capa de servicio para lógica de negocio de avisos electrónicos
"""

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 (
    ElectronicNoticeCreateDTO,
    ElectronicNoticeResponseDTO,
    ElectronicNoticeUpdateDTO,
)
from .models import ElectronicNotice

logger = logging.getLogger(__name__)


class ElectronicNoticeService:
    """Servicio para gestión de avisos electrónicos"""

    @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[ElectronicNotice], int]:
        """Get all electronic notices with pagination"""
        query = db.query(ElectronicNotice).filter(
            ElectronicNotice.tenant_id == tenant_id,
            ElectronicNotice.company_id == company_id
        )

        # Apply filters if provided
        if filters:
            if filters.get("notice_number"):
                query = query.filter(
                    ElectronicNotice.notice_number.ilike(
                        f"%{filters['notice_number']}%"
                    )
                )
            if filters.get("status"):
                query = query.filter(
                    ElectronicNotice.status.ilike(f"%{filters['status']}%")
                )
            if filters.get("pedimento"):
                query = query.filter(
                    ElectronicNotice.pedimento.ilike(
                        f"%{filters['pedimento']}%")
                )

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

        return notices, total

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

    @staticmethod
    def create(
        db: Session, notice_data: ElectronicNoticeCreateDTO, tenant_id: int, company_id: int
    ) -> ElectronicNotice:
        """Create a new electronic notice"""
        try:
            db_notice = ElectronicNotice(
                **notice_data.model_dump(exclude_unset=True),
                tenant_id=tenant_id,
                company_id=company_id
            )

            db.add(db_notice)
            db.commit()
            db.refresh(db_notice)

            return db_notice

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

    @staticmethod
    def update(
        db: Session, id: int, tenant_id: int, notice_data: ElectronicNoticeUpdateDTO, company_id: int
    ) -> Optional[ElectronicNotice]:
        """Update an electronic notice"""
        try:
            db_notice = ElectronicNoticeService.get_by_id(
                db, id, tenant_id, company_id)
            if not db_notice:
                return None

            for key, value in notice_data.model_dump(exclude_unset=True).items():
                setattr(db_notice, key, value)

            db.commit()
            db.refresh(db_notice)
            return db_notice

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

    @staticmethod
    def delete(
        db: Session, id: int, tenant_id: int, company_id: int
    ) -> bool:
        """Delete an electronic notice"""
        try:
            db_notice = ElectronicNoticeService.get_by_id(
                db, id, tenant_id, company_id)
            if not db_notice:
                return False

            db.delete(db_notice)
            db.commit()
            return True

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

    @staticmethod
    def get_by_pedimento(
        db: Session, pedimento: str, tenant_id: int, company_id: int
    ) -> List[ElectronicNotice]:
        """Get all electronic notices by pedimento"""
        return (
            db.query(ElectronicNotice)
            .filter(
                ElectronicNotice.pedimento == pedimento,
                ElectronicNotice.tenant_id == tenant_id,
                ElectronicNotice.company_id == company_id
            )
            .all()
        )

    @staticmethod
    def get_by_status(
        db: Session, status: str, tenant_id: int, company_id: int
    ) -> List[ElectronicNotice]:
        """Get all electronic notices by status"""
        return (
            db.query(ElectronicNotice)
            .filter(
                ElectronicNotice.status == status,
                ElectronicNotice.tenant_id == tenant_id,
                ElectronicNotice.company_id == company_id
            )
            .all()
        )
