from sqlalchemy.orm import Session
from ..schemas.Schemas import DespesaBase, PeriodoLancamento, TipoPeriodoLancamento
from ..models.Despesa import Despesa as ModelDespesa
from ..models.DespesaFixa import DespesaFixa as ModelDespesaFixa
from ..models.DespesaVariavel import DespesaVariavel as ModelDespesaVariavel
from ..models.DespesaAvulsa import DespesaAvulsa as ModelDespesaAvulsa
from ..models.DespesaTempoFixo import DespesaTempoFixo as ModelDespesaTempoFixo, TempoFixoPeriodo
from ..models.DespesaTempoVariavel import DespesaTempoVariavel as ModelDespesaTempoVariavel
from fastapi import HTTPException
from numpy import concatenate

def definir_periodo(periodo: str) -> str:
    if periodo == TempoFixoPeriodo.Diario:
        return TipoPeriodoLancamento.DIARIO
    elif periodo == TempoFixoPeriodo.Semanal:
        return TipoPeriodoLancamento.SEMANAL
    elif periodo == TempoFixoPeriodo.Mensal:
        return TipoPeriodoLancamento.MENSAL
    elif periodo == TempoFixoPeriodo.Bimestral:
        return TipoPeriodoLancamento.BIMESTRAL
    elif periodo == TempoFixoPeriodo.Trimestral:
        return TipoPeriodoLancamento.TRIMESTRAL
    elif periodo == TempoFixoPeriodo.Semestral:
        return TipoPeriodoLancamento.SEMESTRAL
    elif periodo == TempoFixoPeriodo.Anual:
        return TipoPeriodoLancamento.ANUAL
    return TipoPeriodoLancamento.VARIAVEL

def get_periodo_lancamento_despesa(id_despesa: int, session: Session) -> PeriodoLancamento:
    periodo_db = session.query(ModelDespesaTempoFixo).filter_by(id=id_despesa).first()
    if periodo_db:
        return PeriodoLancamento(
            tipo=definir_periodo(periodo_db.tempo_fixo_periodo)
        )
    
    periodo_db = session.query(ModelDespesaTempoVariavel).filter_by(id=id_despesa).first()
    return PeriodoLancamento(
        tipo=TipoPeriodoLancamento.VARIAVEL,
        valor_variavel=periodo_db.tempo_variavel_periodo_dias
    )

def get_despesas_avulsas(session: Session):
    despesas = []
    for despesa in session.query(ModelDespesaAvulsa).all():
        despesa.tipo_despesa = "Avulsa"
        despesas.append(despesa)
    return despesas

def get_despesas_fixas(session: Session):
    despesas = []
    for despesa in session.query(ModelDespesaFixa).all():
        despesa.tipo_despesa = "Fixa"
        despesas.append(despesa)
    return despesas

def get_despesas_variaveis(session: Session):
    despesas = []
    for despesa in session.query(ModelDespesaVariavel).all():
        despesa.tipo_despesa = "Variavel"
        despesas.append(despesa)
    return despesas

def get_despesas(session: Session) -> list[DespesaBase]:
    despesas_avulsas = get_despesas_avulsas(session)
    despesas_fixas = get_despesas_fixas(session)
    despesas_variaveis = get_despesas_variaveis(session)
    return concatenate([despesas_avulsas, despesas_fixas, despesas_variaveis]).tolist()

def add_despesa_fixa(nova_despesa: DespesaBase, session: Session):
    nova_despesa_fixa = ModelDespesaFixa(
        id=nova_despesa.id,
        usuario_id=nova_despesa.usuario_id,
        nome=nova_despesa.nome,
        data=nova_despesa.data,
        modo=nova_despesa.modo,
        descricao=nova_despesa.descricao,
        valor=nova_despesa.valor_primeiro_lancamento
    )
    session.add(nova_despesa_fixa)
    session.commit()
    session.refresh(nova_despesa_fixa)
    return nova_despesa_fixa

def add_despesa_variavel(nova_despesa: DespesaBase, session: Session):
    nova_despesa_variavel = ModelDespesaVariavel(
        id=nova_despesa.id,
        usuario_id=nova_despesa.usuario_id,
        nome=nova_despesa.nome,
        data=nova_despesa.data,
        modo=nova_despesa.modo,
        descricao=nova_despesa.descricao,
        valor=nova_despesa.valor_primeiro_lancamento
    )
    session.add(nova_despesa_variavel)
    session.commit()
    session.refresh(nova_despesa_variavel)
    return nova_despesa_variavel

def add_despesa_avulsa(nova_despesa: DespesaBase, session: Session):
    nova_despesa_avulsa = ModelDespesaAvulsa(
        id=nova_despesa.id,
        usuario_id=nova_despesa.usuario_id,
        nome=nova_despesa.nome,
        data=nova_despesa.data,
        modo=nova_despesa.modo,
        descricao=nova_despesa.descricao,
        valor=nova_despesa.valor_primeiro_lancamento
    )
    session.add(nova_despesa_avulsa)
    session.commit()
    session.refresh(nova_despesa_avulsa)
    return nova_despesa_avulsa

def add_despesa_tempo_fixo(nova_despesa: DespesaBase, session: Session):
    nova_despesa_tempo_fixo = ModelDespesaTempoFixo(
        id=nova_despesa.id,
        tempo_fixo_periodo=nova_despesa.periodo
    )
    session.add(nova_despesa_tempo_fixo)
    session.commit()
    session.refresh(nova_despesa_tempo_fixo)
    return nova_despesa_tempo_fixo

def add_despesa_tempo_variavel(nova_despesa: DespesaBase, session: Session):
    nova_despesa_tempo_variavel = ModelDespesaTempoVariavel(
        id=nova_despesa.id,
        tempo_variavel_periodo_dias=nova_despesa.periodo
    )
    session.add(nova_despesa_tempo_variavel)
    session.commit()
    session.refresh(nova_despesa_tempo_variavel)
    return nova_despesa_tempo_variavel

def delete_despesa(id: int, session: Session):
    db_despesa = session.query(ModelDespesa).filter_by(id=id).first()
    if not db_despesa:
        raise HTTPException(
            status_code=404,
            detail="Despesa não encontrada."
        )

    db_despesa_tempo_fixo = session.query(ModelDespesaTempoFixo).filter_by(id=id).first()
    if db_despesa_tempo_fixo:
        session.delete(db_despesa_tempo_fixo)
        session.commit()

    db_despesa_tempo_variavel = session.query(ModelDespesaTempoVariavel).filter_by(id=id).first()
    if db_despesa_tempo_variavel:
        session.delete(db_despesa_tempo_variavel)
        session.commit()
    
    db_despesa_avulsa = session.query(ModelDespesaAvulsa).filter_by(id=id).first()
    if db_despesa_avulsa:
        session.delete(db_despesa_avulsa)
        session.commit()

    db_despesa_fixa = session.query(ModelDespesaFixa).filter_by(id=id).first()
    if db_despesa_fixa:
        session.delete(db_despesa_fixa)
        session.commit()

    db_despesa_variavel = session.query(ModelDespesaVariavel).filter_by(id=id).first()
    if db_despesa_variavel:
        session.delete(db_despesa_variavel)
        session.commit()
        
    return {
        "detail": "Despesa removida com sucesso."
    }
