from django.shortcuts import render, redirect, get_object_or_404
from apps.estoque.forms import CategoriaInsumoForm, ItemEstoqueForm, MovimentacaoEstoqueForm
from apps.estoque.models import CategoriaInsumo, ItemEstoque, MovimentacaoEstoque
from django.db.models import Sum, F, FloatField, ExpressionWrapper
from django.db.models.functions import Coalesce
from collections import Counter
from django.contrib import messages
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from apps.dashboard.utils import get_user_info
from django.contrib.auth.decorators import login_required
from django.utils import timezone
from datetime import timedelta
from apps.especies.models import Especies

@csrf_exempt
def criar_categoria_insumo_ajax(request):
    print("View 'criar_categoria_insumo_ajax' called")
    print("Request method:", request.method)
    if request.method == 'POST':
        print("POST data:", request.POST)
        form = CategoriaInsumoForm(request.POST)
        if form.is_valid():
            print("Form is valid")
            categoria = form.save()
            print("Categoria criada:", categoria)
            return JsonResponse({
                "success": True,
                "message": "Categoria criada com sucesso!",
                "categoria_id": categoria.id,
                "categoria_nome": categoria.nome
            })
        else:
            print("Form errors:", form.errors)
            return JsonResponse({"success": False, "errors": form.errors})
    else:
        print("Invalid method")
    return JsonResponse({"success": False, "message": "Método inválido"})

def criar_categoria_insumo(request):
    if not request.user.is_authenticated:
        return redirect('index')
    user_info = get_user_info(request.user.id)
    if request.method == 'POST':
        form = CategoriaInsumoForm(request.POST)
        if form.is_valid():
            form.save()
            messages.success(request, "Categoria criada com sucesso.")
            return redirect('lista_categorias_insumo')
    else:
        form = CategoriaInsumoForm()
    return render(request, 'estoque/criar_categoria_insumo.html', {'form': form, 'user_info': user_info})

def lista_categorias_insumo(request):
    if not request.user.is_authenticated:
        return redirect('index')
    user_info = get_user_info(request.user.id)
    categorias = CategoriaInsumo.objects.all()
    return render(request, 'estoque/lista_categorias_insumo.html', {'categorias': categorias, 'user_info': user_info})

def criar_item_estoque(request):
    if not request.user.is_authenticated:
        return redirect('index')
    
    user_info = get_user_info(request.user.id)

    # Busca as espécies cadastradas no banco
    especies = Especies.objects.all()

    if request.method == 'POST':
        form = ItemEstoqueForm(request.POST)
        if form.is_valid():
            form.save()
            messages.success(request, "Item de estoque criado com sucesso.")
            return redirect('lista_itens_estoque')
    else:
        form = ItemEstoqueForm()

    context = {
        'form': form,
        'user_info': user_info,
        'especies': especies,  # envia para o template para preencher o datalist
    }

    return render(request, 'estoque/criar_item_estoque.html', context)


def lista_itens_estoque(request):
    if not request.user.is_authenticated:
        return redirect('index')
    user_info = get_user_info(request.user.id)

    categoria_id = request.GET.get('categoria')
    categorias = CategoriaInsumo.objects.all()
    hoje = timezone.now().date()
    proximos_30_dias = hoje + timedelta(days=30)

    # Defina 'itens' antes de usá-la
    if categoria_id:
        itens = ItemEstoque.objects.filter(categoria_id=categoria_id, quantidade__gt=0)
    else:
        itens = ItemEstoque.objects.filter(quantidade__gt=0)

    # Adiciona atributos para indicar se o item está vencido ou próximo do vencimento
    for item in itens:
        if item.data_validade:
            if item.data_validade < hoje:
                item.vencido = True
                item.proximo_vencimento = False
            elif hoje <= item.data_validade <= proximos_30_dias:
                item.vencido = False
                item.proximo_vencimento = True
            else:
                item.vencido = False
                item.proximo_vencimento = False
        else:
            # Caso o item não tenha data de validade, consideramos como não vencido
            item.vencido = False
            item.proximo_vencimento = False

    context = {
        'itens': itens,
        'categorias': categorias,
        'categoria_selecionada': int(categoria_id) if categoria_id else None,
        'user_info': user_info,
    }
    return render(request, 'estoque/lista_itens_estoque.html', context)



def editar_item_estoque(request, item_id):
    if not request.user.is_authenticated:
        return redirect('index')
    user_info = get_user_info(request.user.id)
    item = get_object_or_404(ItemEstoque, pk=item_id)
    if request.method == 'POST':
        form = ItemEstoqueForm(request.POST, instance=item)
        if form.is_valid():
            form.save()
            messages.success(request, "Item de estoque atualizado com sucesso.")
            return redirect('lista_itens_estoque')
    else:
        form = ItemEstoqueForm(instance=item)
    return render(request, 'estoque/editar_item_estoque.html', {'form': form, 'item': item, 'user_info': user_info})

def deletar_item_estoque(request, item_id):
    if not request.user.is_authenticated:
        return redirect('index')
    try:
        item = ItemEstoque.objects.get(pk=item_id)
        item.delete()
        messages.success(request, "Item de estoque excluído com sucesso.")
    except ItemEstoque.DoesNotExist:
        messages.error(request, "Item de estoque não encontrado.")
    return redirect('lista_itens_estoque')

@login_required
def registrar_movimentacao(request):
    if not request.user.is_authenticated:
        return redirect('index')
    user_info = get_user_info(request.user.id)
    item_id = request.GET.get('item_id')
    initial_data = {}
    if item_id:
        item = get_object_or_404(ItemEstoque, pk=item_id)
        initial_data['item'] = item

    if request.method == 'POST':
        form = MovimentacaoEstoqueForm(request.POST)
        if form.is_valid():
            movimentacao = form.save(commit=False)
            movimentacao.responsavel = request.user
            try:
                movimentacao.save()
                messages.success(request, "Movimentação registrada com sucesso.")
                return redirect('lista_itens_estoque')
            except ValueError as e:
                form.add_error(None, str(e))
    else:
        form = MovimentacaoEstoqueForm(initial=initial_data)
    return render(request, 'estoque/registrar_movimentacao.html', {'form': form, 'user_info': user_info})

@login_required
def lista_movimentacoes(request):
    if not request.user.is_authenticated:
        return redirect('index')
    user_info = get_user_info(request.user.id)
    movimentacoes = MovimentacaoEstoque.objects.order_by('-data')
    return render(request, 'estoque/lista_movimentacoes.html', {'movimentacoes': movimentacoes, 'user_info': user_info})



def relatorio_insumos_por_categoria(request):
    if not request.user.is_authenticated:
        return redirect('index')

    user_info = get_user_info(request.user.id)
    categorias = CategoriaInsumo.objects.prefetch_related('itens')
    categoria_data = []

    for categoria in categorias:
        total_quantidade = 0
        total_custo = 0
        unidade_mais_usada = ''
        unidades = []

        for item in categoria.itens.all():
            if item.quantidade:
                total_quantidade += float(item.quantidade)
            if item.custo is not None:
                total_custo += float(item.custo)
            elif item.quantidade and item.custo_unitario:
                total_custo += float(item.quantidade) * float(item.custo_unitario)

            if item.unidade_medida:
                unidades.append(item.unidade_medida)

        # Pega a unidade mais comum
        if unidades:
            unidade_mais_usada = Counter(unidades).most_common(1)[0][0]

        # Mapeamento de unidades para exibição amigável
        UNIDADE_DISPLAY = {
            'kg': 'Kilogramas',
            'g': 'Gramas',
            'l': 'Litros',
            'ml': 'Mililitros',
            'un': 'Unidades',
            'sc': 'Sacos',
        }

        categoria_data.append({
            'nome': categoria.nome,
            'total_quantidade': total_quantidade,
            'total_custo': total_custo,
            'unidade_medida': unidade_mais_usada,
            'unidade_display': UNIDADE_DISPLAY.get(unidade_mais_usada, ''),
        })

    context = {
        'categoria_data': categoria_data,
        'user_info': user_info,
    }
    return render(request, 'estoque/relatorio_insumos_por_categoria.html', context)


def itens_proximos_vencimento(request):
    if not request.user.is_authenticated:
        return redirect('index')
    user_info = get_user_info(request.user.id)

    hoje = timezone.now().date()
    proximos_30_dias = hoje + timedelta(days=30)

    itens_vencendo = ItemEstoque.objects.filter(
        data_validade__range=(hoje, proximos_30_dias)
    ).annotate(
        dias_restantes=F('data_validade') - hoje
    )

    # Calcula os dias restantes para cada item
    for item in itens_vencendo:
        item.dias_restantes = (item.data_validade - hoje).days

    context = {
        'itens_vencendo': itens_vencendo,
        'user_info': user_info,
    }
    return render(request, 'estoque/itens_proximos_vencimento.html', context)

def relatorio_custos_insumos(request):
    if not request.user.is_authenticated:
        return redirect('index')
    user_info = get_user_info(request.user.id)

    # Anota o custo total de cada item
    itens = ItemEstoque.objects.annotate(
        custo_total=F('quantidade') * F('custo_unitario')
    )

    # Calcula o custo total por categoria
    categorias = CategoriaInsumo.objects.annotate(
        total_custo=Sum(
            F('itens__quantidade') * F('itens__custo_unitario'),
            output_field=FloatField()
        )
    )

    # Calcula o custo total geral
    total_custo_geral = itens.aggregate(
        total_custo=Sum('custo_total')
    )['total_custo'] or 0

    context = {
        'itens': itens,
        'categorias': categorias,
        'total_custo_geral': total_custo_geral,
        'user_info': user_info,
    }
    return render(request, 'estoque/relatorio_custos_insumos.html', context)