from django.shortcuts import render, redirect
from apps.dashboard.forms import LoginForms
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from apps.dashboard.utils import get_user_info
from django.http import HttpResponseForbidden
from apps.especies.models import Especies
from apps.lotes.models import CadastroLote
from django.db.models import Sum, F, functions
from apps.estufa.models import Estufa
from apps.repique.models import Repique
from apps.saidas.models import SaidasEspecies, Saidas
from django.db.models.functions import ExtractMonth
import datetime
import json
from django.db.models import Count, Sum, Case, When, BooleanField
from apps.protocolos.models import Protocolo, ProtocoloSemeadura
from django.db.models import Sum
from django.db.models.functions import ExtractMonth
from apps.funcionario.models import UsuarioFuncionario
from django.shortcuts import get_object_or_404
from apps.metas.models import MetasModels  # Importação do modelo MetasModels
from apps.metas.forms import MetasForm
import datetime
from django.utils.timezone import now
from apps.funcionario.models import UsuarioFuncionario


def login(request):
    form = LoginForms()

    if request.method == 'POST':
        form = LoginForms(request.POST)

        if form.is_valid():
            nome_usuario = form['nome_usuario'].value()
            senha = form['senha'].value()

            usuario = auth.authenticate(
                request, username=nome_usuario, password=senha)
            if usuario is not None:
                auth.login(request, usuario)

                # Busca o Funcionario relacionado ao User autenticado
                funcionario = get_object_or_404(
                    UsuarioFuncionario, usuario=usuario).funcionario
                messages.success(
                    request, f"Bem-vindo, {funcionario.nome_completo}!")

                return redirect('dashboard_one', user_id=usuario.id)
            else:
                messages.error(
                    request, 'Login falhou. Verifique suas credenciais.')
                return redirect('login')

    return render(request, 'dashboard/login.html', {"form": form})


@login_required
def dashboard_one(request, user_id):
    if request.user.id != user_id:
        return HttpResponseForbidden("Você não tem permissão para acessar este perfil.")

    # Query para pegar os protocolos finalizados com dados de semeadura
    protocolos_finalizados_semeaduras = ProtocoloSemeadura.objects.select_related('protocolo', 'semeadura').filter(
        protocolo__finalizado=True  # Apenas protocolos finalizados
    )

    # Agrupando os dados dos protocolos finalizados
    grouped_finalizados = {}
    total_mudas_vendidas = 0  # Variável para armazenar o total de mudas vendidas

    # Inicializa a lista de vendas por mês
    vendas_por_mes_lista = [0] * 12

    for ps in protocolos_finalizados_semeaduras:
        protocolo_id = ps.protocolo.id
        if protocolo_id not in grouped_finalizados:
            cliente_nome = ps.protocolo.cliente_fisico.nome_completo if ps.protocolo.tipo_cliente == 'F' else ps.protocolo.cliente_empresa.nome_fantasia
            grouped_finalizados[protocolo_id] = {
                'numero_protocolo': ps.protocolo.num_protocolo,
                'data_saida_protocolo': ps.protocolo.data_saida_protocolo,
                'quantidade_mudas': 0,
                'cliente_nome': cliente_nome
            }

        # Soma a quantidade de mudas para cada protocolo
        quantidade_mudas = ps.qtd_especie if ps.qtd_especie else 0
        grouped_finalizados[protocolo_id]['quantidade_mudas'] += quantidade_mudas
        total_mudas_vendidas += quantidade_mudas

        if ps.protocolo.data_saida_protocolo:  # <-- agora dentro do loop
        # Agrupa as vendas por mês com base na data de saída do protocolo
          mes_venda = ps.protocolo.data_saida_protocolo.month - 1  # Ajusta o índice do mês
          vendas_por_mes_lista[mes_venda] += quantidade_mudas

    # Converte os valores do dicionário grouped_finalizados para uma lista
    grouped_finalizados_list = list(grouped_finalizados.values())

    # Define o ano atual
    ano_atual = datetime.date.today().year

    # Agrupa protocolos finalizados por mês e soma a quantidade de mudas usando data_saida_protocolo
    protocolos_por_mes = ProtocoloSemeadura.objects.filter(
        protocolo__finalizado=True,
        protocolo__data_saida_protocolo__year=ano_atual
    ).annotate(
        mes=ExtractMonth('protocolo__data_saida_protocolo')
    ).values('mes').annotate(
        total_mudas=Sum('qtd_especie')
    ).order_by('mes')

    # Inicializa uma lista com zeros para cada mês (Jan-Dez)
    dados_protocolos = [0] * 12

    # Preenche a lista com os valores somados
    for protocolo in protocolos_por_mes:
        mes_index = protocolo['mes'] - 1  # Ajusta o índice do mês
        dados_protocolos[mes_index] = int(protocolo['total_mudas'])

    # Dentro da sua função dashboard_one
    dez_maiores_lotes = CadastroLote.objects.all().order_by(
        '-entrada_sementes_kg')[:10]

    # Mudas Mais produzidas ---------------------
    mudas_mais_produzidas = Repique.objects.all()
    mudas_produzidas_nao_finalizadas = Repique.objects.filter(
        finalizado=False).order_by('-quantidade_repicada')[:10]
    mudas_produzidas_finalizadas = Repique.objects.filter(
        finalizado=True).order_by('-quantidade_repicada')[:10]
    mudas_produzidas_agrupadas = mudas_mais_produzidas.values('semeadura__lote__especie__nome_popular',
                                                              'semeadura__lote__especie__especies').annotate(
        total_mudas_produzidas=Sum('quantidade_repicada')).order_by('-total_mudas_produzidas')[:10]
    # -------------------------------------------

    # Mudas Mais Vendidas -----------------------
    mudas_mais_vendidas = SaidasEspecies.objects.all()

    # Verifica se há data de venda definida para determinar se as mudas estão finalizadas
    mudas_mais_vendidas_nao_finalizadas = mudas_mais_vendidas.annotate(
        tem_data_venda=Case(
            When(data_venda__isnull=True, then=False),
            default=True,
            output_field=BooleanField()
        )
    ).filter(tem_data_venda=False).order_by('-qtd_especie')[:10]

    # Filtra as mudas com data de venda para determinar as finalizadas
    mudas_mais_vendidas_finalizadas = mudas_mais_vendidas.annotate(
        tem_data_venda=Case(
            When(data_venda__isnull=True, then=False),
            default=True,
            output_field=BooleanField()
        )
    ).filter(tem_data_venda=True).order_by('-qtd_especie')[:10]

    # Agrupa as mudas mais vendidas baseadas no nome popular da espécie e calcula o total de vendas
    mudas_mais_vendidas_agrupadas = mudas_mais_vendidas.values('semeadura__lote__especie__nome_popular',
                                                               'semeadura__lote__especie__especies').annotate(
        total_vendas=Sum('qtd_especie')).order_by('-total_vendas')[:10]
    # -------------------------------------------

    # Mortalidade de Mudas ----------------------
    maiores_mortalidades = Estufa.objects.all()
    maiores_mortalidades_nao_finalizadas = Estufa.objects.filter(
        finalizado=False).order_by('-quantidade_mortalidade')[:10]
    maiores_mortalidades_finalizadas = Estufa.objects.filter(
        finalizado=True).order_by('-quantidade_mortalidade')[:10]
    maiores_mortalidades_agrupadas = maiores_mortalidades.values('semeadura__lote__especie__nome_popular',
                                                                 'semeadura__lote__especie__especies').annotate(
        total_mortalidade=Sum('quantidade_mortalidade')).order_by('-total_mortalidade')[:10]
    # -------------------------------------------

    anos = range(ano_atual, ano_atual - 4, -1)  # Ajuste conforme necessário

    


    dados_anuais = []
    for ano in anos:
        total_produzidas_ano = Repique.objects.filter(
            data_repique__year=ano
        ).aggregate(
            total=Sum('quantidade_repicada')
        )['total'] or 0

        total_vendidas_ano = ProtocoloSemeadura.objects.filter(
            protocolo__finalizado=True,
            protocolo__data_saida_protocolo__year=ano
        ).aggregate(
            total=Sum('qtd_especie')
        )['total'] or 0

        total_mortalidade_ano = Estufa.objects.filter(
            data_estufa__year=ano
        ).aggregate(
            total=Sum('quantidade_mortalidade')
        )['total'] or 0

        dados_anuais.append({
            'ano': ano,
            'total_sementes': int(total_produzidas_ano),
            'total_vendas': int(total_vendidas_ano),
            'total_mortalidade': int(total_mortalidade_ano),
        })


    # Agrupa e soma as quantidades repicadas por mês para o ano atual
    repiques_por_mes = Repique.objects.filter(data_repique__year=ano_atual).annotate(
        mes=ExtractMonth('data_repique')
    ).values('mes').annotate(
        total_repicado=Sum('quantidade_repicada')
    ).order_by('mes')

    # Inicializa uma lista com zeros para cada mês (Jan-Dec)
    dados_repicados = [0] * 12

    # Preenche a lista com os valores somados
    for repique in repiques_por_mes:
        # O índice do mês no array é mes-1, pois Janeiro é 1 mas sua posição no array é 0
        dados_repicados[repique['mes'] - 1] = int(repique['total_repicado'])

    # Filtra vendas acumuladas por mês considerando apenas vendas finalizadas
    vendas_por_mes = SaidasEspecies.objects.filter(
        data_venda__year=ano_atual,
        semeadura__protocolo__finalizado=True
    ).annotate(
        mes=ExtractMonth('data_venda')
    ).values('mes').annotate(
        total_vendido=Sum('qtd_especie')
    ).order_by('mes')

    # Inicializa uma lista com zeros para cada mês (Jan-Dec)
    dados_vendas = [0.0] * 12

    # Preenche a lista com os valores somados
    for venda in vendas_por_mes:
        mes_index = venda['mes'] - 1
        dados_vendas[mes_index] = float(
            venda['total_vendido']) if venda['total_vendido'] is not None else 0.0

    # Soma total das entradas de sementes em quilogramas
    total_sementes_decimal = CadastroLote.objects.aggregate(
        Sum('entrada_sementes_kg'))['entrada_sementes_kg__sum']
    total_sementes = float(
        total_sementes_decimal) if total_sementes_decimal is not None else 0

    # Soma total das quantidades de mortalidade em Estufa
    total_mortalidade_decimal = Estufa.objects.aggregate(
        Sum('quantidade_mortalidade'))['quantidade_mortalidade__sum']
    total_mortalidade = int(float(total_mortalidade_decimal)
                            ) if total_mortalidade_decimal is not None else 0

    # Soma total das quantidades repicadas em Repique
    total_repicadas_decimal = Repique.objects.aggregate(Sum('quantidade_repicada'))[
        'quantidade_repicada__sum']
    total_repicadas = int(float(total_repicadas_decimal)
                          ) if total_repicadas_decimal is not None else 0

    # Soma total das quantidades de espécies em SaidasEspecies
    total_qtd_especies_decimal = SaidasEspecies.objects.aggregate(Sum('qtd_especie'))[
        'qtd_especie__sum']
    total_qtd_especies = int(float(total_qtd_especies_decimal)
                             ) if total_qtd_especies_decimal is not None else 0

    user_info = get_user_info(user_id=user_id)

    numero_de_especies = Especies.objects.count()
    ultimas_especies = Especies.objects.all().order_by('-id')[:10]

    numero_de_lotes = CadastroLote.objects.count()
    ultimos_lotes = CadastroLote.objects.all().order_by('-id')[:10]

    hoje = now().date()

    # Filtrar apenas as metas não finalizadas do usuário
    metas = MetasModels.objects.filter(
        criado_por=request.user, finalizado=False).order_by('data_final')

    # Selecionar apenas as primeiras 3 metas
    metas_display = metas[:3]

    metas_info = []
    for meta in metas_display:
        # Determinar o status de cada meta
        if meta.data_final < hoje:
            if meta.meta_atingida:
                status = "Concluída"
            else:
                status = "Falhou"
        else:
            status = "Em andamento"

        # Calcular o percentual de cumprimento
        if meta.quantidade > 0:
            percentual = (meta.quantidade_acumulada / meta.quantidade) * 100
            percentual = min(percentual, 100)  # Limitar a 100%
        else:
            percentual = 0

        # Obter o nome completo do funcionário que criou a meta
        if meta.criado_por:
            try:
                usuario_funcionario = UsuarioFuncionario.objects.get(
                    usuario=meta.criado_por)
                criado_por_nome = usuario_funcionario.funcionario.nome_completo
            except UsuarioFuncionario.DoesNotExist:
                criado_por_nome = 'Desconhecido'
        else:
            criado_por_nome = 'Desconhecido'

        metas_info.append({
            'especie': meta.especie.nome_popular,
            'tipo_meta': meta.get_tipo_meta_display(),
            'data_inicial': meta.data_inicial,
            'data_final': meta.data_final,
            'quantidade_meta': meta.quantidade,  # Substituído para usar 'quantidade'
            # Substituído para usar 'quantidade_acumulada'
            'quantidade_feita': meta.quantidade_acumulada,
            'status': status,
            # Armazena como inteiro para facilitar
            'percentual': int(percentual),
            'criado_por': criado_por_nome,  # Nome completo do funcionário
        })

    # Contar o total de metas para decidir se exibe o botão "Ver Mais"
    total_metas = metas.count()

    # Passa o total_mortalidade junto com os outros valores para o contexto
    return render(request, 'dashboard/dashboard_one.html', {
        "user_info": user_info,
        'user_id': user_id,

        'numero_de_especies': numero_de_especies,
        'ultimas_especies': ultimas_especies,

        'numero_de_lotes': numero_de_lotes,
        'ultimos_lotes': ultimos_lotes,

        'total_sementes': total_sementes,
        'total_mortalidade': total_mortalidade,
        'total_repicada': total_repicadas,
        'total_qtd_especies': total_qtd_especies,
        'dados_repicados': json.dumps(dados_repicados),
        'dados_anuais': json.dumps(dados_anuais),
        'dez_maiores_lotes': dez_maiores_lotes,

        'mudas_produzidas_nao_finalizadas': mudas_produzidas_nao_finalizadas,
        'mudas_produzidas_finalizadas': mudas_produzidas_finalizadas,
        'mudas_produzidas_agrupadas': mudas_produzidas_agrupadas,

        'mudas_mais_vendidas_nao_finalizadas': mudas_mais_vendidas_nao_finalizadas,
        'mudas_mais_vendidas_finalizadas': mudas_mais_vendidas_finalizadas,
        'mudas_mais_vendidas_agrupadas': mudas_mais_vendidas_agrupadas,

        'maiores_mortalidades_nao_finalizadas': maiores_mortalidades_nao_finalizadas,
        'maiores_mortalidades_finalizadas': maiores_mortalidades_finalizadas,
        'maiores_mortalidades_agrupadas': maiores_mortalidades_agrupadas,

        'grouped_finalizados': grouped_finalizados.values(),
        'total_mudas_vendidas': total_mudas_vendidas,
        'dados_vendas': json.dumps(dados_vendas),
        'dados_protocolos': json.dumps(dados_protocolos),
        'metas_info': metas_info,
        'total_metas': total_metas,
    })


def logout(request):
    auth.logout(request)
    messages.success(request, "Logout efetuado com sucesso!")
    return redirect('login')


def error(request):
    if not request.user.is_authenticated:
        return redirect('index')
    user_info = get_user_info(request.user.id)
    return render(request, 'dashboard/error.html', {"user_info": user_info})
