import logging

from datetime import date
from typing import Optional, List
from sqlalchemy import select, and_
from sqlalchemy.ext.asyncio import AsyncSession
from models.omie_contrato import OmieContrato
from models.omie_contrato_servico import OmieContratoServico
from models.omie_contrato_vencimento import OmieContratoVencimento
from models.omie_contrato_departamento import OmieContratoDepartamento

logger = logging.getLogger(__name__)

class OmieContratoCRUD:
    async def list(
        self,
        db: AsyncSession,
        *,
        cnpj: Optional[str] = None,
        codigo_contrato: Optional[str] = None,
        status: Optional[str] = None,
    ) -> List[OmieContrato]:
        """Lista contratos com filtros opcionais"""
        table_name = OmieContrato.__tablename__
        logger.info(f"OmieContratoCRUD.list chamado - Tabela: {table_name}")
        try:
            stmt = select(OmieContrato)
            conditions = []
            
            if cnpj:
                cnpj_limpo = cnpj.replace('.', '').replace('/', '').replace('-', '').strip()
                conditions.append(OmieContrato.cnpj.like(f"%{cnpj_limpo}%"))
            
            if codigo_contrato:
                conditions.append(OmieContrato.codigo_contrato == codigo_contrato)
            
            if status:
                conditions.append(OmieContrato.status == status)
            
            if conditions:
                stmt = stmt.where(and_(*conditions))
            
            result = await db.execute(stmt)
            contratos = list(result.scalars().all())
            logger.info(f"Query retornou {len(contratos)} registros da tabela {table_name}")
            return contratos
            
        except Exception as e:
            logger.error(f"Erro em OmieContratoCRUD.list: {e}", exc_info=True)
            raise

class OmieContratoServicoCRUD:
    async def list(
        self,
        db: AsyncSession,
        *,
        codigo_contrato: Optional[str] = None,
    ) -> List[OmieContratoServico]:
        """Lista serviços de contratos com filtro opcional"""
        table_name = OmieContratoServico.__tablename__
        logger.info(f"OmieContratoServicoCRUD.list chamado - Tabela: {table_name}")
        try:
            stmt = select(OmieContratoServico)
            
            if codigo_contrato:
                stmt = stmt.where(OmieContratoServico.codigo_contrato == codigo_contrato)
            
            result = await db.execute(stmt)
            servicos = list(result.scalars().all())
            logger.info(f"Query retornou {len(servicos)} registros da tabela {table_name}")
            return servicos
            
        except Exception as e:
            logger.error(f"Erro em OmieContratoServicoCRUD.list: {e}", exc_info=True)
            raise

class OmieContratoDepartamentoCRUD:
    async def list(
        self,
        db: AsyncSession,
        *,
        codigo_contrato: Optional[str] = None,
    ) -> List[OmieContratoDepartamento]:
        """Lista departamentos de contratos com filtro opcional"""
        table_name = OmieContratoDepartamento.__tablename__
        logger.info(f"OmieContratoDepartamentoCRUD.list chamado - Tabela: {table_name}")
        try:
            stmt = select(OmieContratoDepartamento)
            
            if codigo_contrato:
                stmt = stmt.where(OmieContratoDepartamento.codigo_contrato == codigo_contrato)
            
            result = await db.execute(stmt)
            departamentos = list(result.scalars().all())
            logger.info(f"Query retornou {len(departamentos)} registros da tabela {table_name}")
            return departamentos
            
        except Exception as e:
            logger.error(f"Erro em OmieContratoDepartamentoCRUD.list: {e}", exc_info=True)
            raise

class OmieContratoVencimentoCRUD:
    async def list(
        self,
        db: AsyncSession,
        *,
        codigo_contrato: Optional[str] = None,
        data_inicio: Optional[date] = None,
        data_fim: Optional[date] = None,
        status: Optional[str] = None,
    ) -> List[OmieContratoVencimento]:
        """Lista vencimentos de contratos com filtros opcionais"""
        table_name = OmieContratoVencimento.__tablename__
        logger.info(f"OmieContratoVencimentoCRUD.list chamado - Tabela: {table_name}")
        try:
            stmt = select(OmieContratoVencimento)
            conditions = []
            
            if codigo_contrato:
                conditions.append(OmieContratoVencimento.codigo_contrato == codigo_contrato)
            
            if data_inicio:
                conditions.append(OmieContratoVencimento.data_vencimento >= data_inicio)
            
            if data_fim:
                conditions.append(OmieContratoVencimento.data_vencimento <= data_fim)
            
            if status:
                conditions.append(OmieContratoVencimento.status == status)
            
            if conditions:
                stmt = stmt.where(and_(*conditions))
            
            result = await db.execute(stmt)
            vencimentos = list(result.scalars().all())
            logger.info(f"Query retornou {len(vencimentos)} registros da tabela {table_name}")
            return vencimentos
            
        except Exception as e:
            logger.error(f"Erro em OmieContratoVencimentoCRUD.list: {e}", exc_info=True)
            raise

crud_contrato = OmieContratoCRUD()
crud_servico = OmieContratoServicoCRUD()
crud_departamento = OmieContratoDepartamentoCRUD()
crud_vencimento = OmieContratoVencimentoCRUD()