from sqlalchemy.orm import Session
from sqlalchemy import asc
from fastapi import HTTPException
from ..schemas.Schemas import MovimentacaoEstoque, MovimentacaoEstoqueCadastro, MovimentacaoEstoqueAtualizacao, EstoqueProduto, Produto as SchemaProduto
from ..models.MovimentacaoEstoque import MovimentacaoEstoque as ModelMovimentacaoEstoque, SituacaoMovimentacaoEstoque
from .Produto import Produto

def buscar_movimentacoes_do_produto(id_produto: int, session: Session) -> list[MovimentacaoEstoque]:
    return session.query(ModelMovimentacaoEstoque).filter_by(produto_id = id_produto).order_by(asc(ModelMovimentacaoEstoque.data_solicitacao)).all()

def buscar_estoque_completo(session: Session) -> list[EstoqueProduto]:
    crud_produto = Produto()

    estoque: list[EstoqueProduto] = []
    for produto in crud_produto.get_produtos(session):
        quantidade_total_no_estoque = 0
        quantidade_total_reservado = 0

        movimentacoes = buscar_movimentacoes_do_produto(produto.id, session)
        for movimentacao in movimentacoes:
            if movimentacao.data_execucao is not None:
                quantidade_total_no_estoque += movimentacao.quantidade
            elif movimentacao.data_cancelamento is None:
                quantidade_total_reservado += movimentacao.quantidade if movimentacao.quantidade > 0 else movimentacao.quantidade * -1

        estoque.append(EstoqueProduto(
            produto = SchemaProduto(
                id = produto.id,
                nome = produto.nome,
                valor = produto.valor
            ),
            total_no_estoque = quantidade_total_no_estoque,
            total_reservado = quantidade_total_reservado
        ))

    return estoque


def adicionar_movimentacao_de_estoque(movimentacao: MovimentacaoEstoqueCadastro, session: Session) -> MovimentacaoEstoque:
    if movimentacao.situacao is None or movimentacao.situacao is SituacaoMovimentacaoEstoque.Solicitado:
        movimentacao = ModelMovimentacaoEstoque(
            orcamento_id = movimentacao.orcamento_id,
            quantidade = movimentacao.quantidade,
            produto_id = movimentacao.produto_id,
            situacao = SituacaoMovimentacaoEstoque.Solicitado,
            data_solicitacao = movimentacao.data
        )
    else:
        movimentacao = ModelMovimentacaoEstoque(
            quantidade = movimentacao.quantidade,
            produto_id = movimentacao.produto_id,
            orcamento_id = movimentacao.orcamento_id,
            situacao = SituacaoMovimentacaoEstoque.Executado,
            data_solicitacao = movimentacao.data,
            data_execucao = movimentacao.data
        )
    
    session.add(movimentacao)
    session.commit()
    session.refresh(movimentacao)

    return movimentacao

def update_movimentacao_de_estoque(movimentacao: MovimentacaoEstoqueAtualizacao, session: Session) -> MovimentacaoEstoque:
    db_movimentacao_estoque = session.query(ModelMovimentacaoEstoque).filter_by(id = movimentacao.id).first()
    
    if not db_movimentacao_estoque:
        raise HTTPException(
            status_code = 404,
            detail = "Movimentação de estoque não encontrada!"
        )
    
    if movimentacao.situacao is not None:
        db_movimentacao_estoque.situacao = movimentacao.situacao

    if movimentacao.quantidade is not None:
        db_movimentacao_estoque.quantidade = movimentacao.quantidade

    if movimentacao.situacao == SituacaoMovimentacaoEstoque.Cancelado:
        db_movimentacao_estoque.data_cancelamento = movimentacao.data

    elif movimentacao.situacao == SituacaoMovimentacaoEstoque.Executado:
        db_movimentacao_estoque.data_execucao = movimentacao.data

    session.add(db_movimentacao_estoque)
    session.commit()
    session.refresh(db_movimentacao_estoque)

    return db_movimentacao_estoque
