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

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

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

from . import dto, models

logger = logging.getLogger(__name__)


class SignatureService:
    """Servicio para gestión de firmas"""

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

        if filters:
            if filters.get("code"):
                query = query.filter(
                    models.Signature.code.ilike(f"%{filters['code']}%"))

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

        return signatures, total

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

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

    @staticmethod
    def create(
        db: Session,
        signature_data: dto.SignatureCreateDTO,
        tenant_id: int,
        company_id: int,
    ) -> models.Signature:
        """Create a new signature"""
        new_signature = models.Signature(
            **signature_data.model_dump(), tenant_id=tenant_id, company_id=company_id
        )
        try:
            db.add(new_signature)
            db.commit()
            db.refresh(new_signature)
            return new_signature
        except IntegrityError as exc:
            db.rollback()
            # Constraint names: signatures_code_unique (code, tenant_id, company_id)
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Ya existe una firma con ese código para esta compañía",
            ) from exc

    @staticmethod
    def update(
        db: Session,
        signature_id: int,
        tenant_id: int,
        signature_data: dto.SignatureUpdateDTO,
        company_id: int,
    ) -> Optional[models.Signature]:
        """Update a signature"""
        signature = SignatureService.get_by_id(
            db, signature_id, tenant_id, company_id)
        if not signature:
            return None

        for key, value in signature_data.model_dump(exclude_unset=True).items():
            setattr(signature, key, value)

        db.commit()
        db.refresh(signature)
        return signature

    @staticmethod
    def delete(
        db: Session, signature_id: int, tenant_id: int, company_id: int
    ) -> bool:
        """Delete a signature"""
        signature = SignatureService.get_by_id(
            db, signature_id, tenant_id, company_id)
        if not signature:
            return False

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