# views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from apps.protocolos.forms import ProtocoloForm, ProtocoloSemeaduraFormSet, ProtocoloSemeaduraForm, ProtocoloInfoForm
from apps.dashboard.utils import get_user_info
from django.http import JsonResponse
from apps.clientes.models import ClientesModels, EmpresasModels
from apps.lotes.models import Semeadura
from apps.estufa.models import Estufa, Selecao
from apps.repique.models import Repique
from apps.saidas.models import Saidas
from apps.protocolos.models import ProtocoloSemeadura, Protocolo, ProtocoloFinalizado, ProtocoloSemeaduraFinalizado
from django.db.models import Subquery, OuterRef, Sum, Max, Exists
from django.forms import inlineformset_factory
from django.db import IntegrityError
from django.template.loader import render_to_string
from decimal import Decimal
from django.utils import timezone

from django.http import HttpResponse
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, Image
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from io import BytesIO
from datetime import datetime
from django.core.files.storage import default_storage
from apps.saidas.models import SaidasEspecies
from django.templatetags.static import static
from django.conf import settings
from django.shortcuts import get_object_or_404
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, Image
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from io import BytesIO
from datetime import datetime
from django.http import HttpResponse
from django.contrib.staticfiles.storage import staticfiles_storage
from apps.saidas.models import SaidasEspecies
from decimal import Decimal, InvalidOperation
from django.db import transaction
import logging
from decimal import InvalidOperation
from babel.numbers import format_currency

logger = logging.getLogger(__name__)

def get_lista_saidas_data():
    semeaduras = Semeadura.objects.annotate(
        total_saida=Sum('saidas__quantidade_saidas'),
        total_venda=Sum('saidasespecies__qtd_especie'),
        total_repique=Subquery(
            Repique.objects.filter(
                semeadura=OuterRef('pk')
            ).values('semeadura').annotate(
                total_repique=Sum('quantidade_repicada')
            ).values('total_repique')[:1]
        ),
        total_mortalidade_estufa=Subquery(
            Estufa.objects.filter(
                semeadura=OuterRef('pk')
            ).values('semeadura').annotate(
                total_mortalidade=Sum('quantidade_mortalidade')
            ).values('total_mortalidade')[:1]
        ),
        total_quantidade_selecao=Subquery(
            Selecao.objects.filter(
                semeadura=OuterRef('pk'),
                quantidade_selecao__gt=0
            ).values('semeadura').annotate(
                total_selecao=Sum('quantidade_selecao')
            ).values('total_selecao')[:1]
        ),
        ultima_data_saida=Max('saidas__data_saidas')
    ).filter(
        Exists(
            Selecao.objects.filter(
                semeadura=OuterRef('pk'),
                quantidade_selecao__gt=0
            )
        ),
        ~Exists(
            Saidas.objects.filter(
                semeadura=OuterRef('pk'),
                finalizado=True
            )
        ),
        ~Exists(
            ProtocoloSemeaduraFinalizado.objects.filter(
                semeadura=OuterRef('pk'),
                finalizado=True
            )
        )
    ).select_related('lote__especie')

    saidas = []

    for semeadura in semeaduras:
        total_quantidade_selecao = semeadura.total_quantidade_selecao if semeadura.total_quantidade_selecao else 0
        total_venda = semeadura.total_venda if semeadura.total_venda else 0
        
        # Verificação e log de depuração para valores negativos
        diferenca_qtd = total_quantidade_selecao - total_venda
        if diferenca_qtd < 0:
            logger.warning(f"Diferença negativa encontrada para Semeadura ID {semeadura.id}: Quantidade Selecao {total_quantidade_selecao}, Qtd Especie {total_venda}, Diferenca {diferenca_qtd}")
        
        # Forçar diferença a ser no mínimo 0
        diferenca_qtd = max(0, diferenca_qtd)

        if diferenca_qtd == 0:
            continue

        selecoes = Selecao.objects.filter(semeadura=semeadura).order_by('-data_selecao')
        venda = selecoes.first().venda if selecoes.exists() else False

        saidas_data = []
        saidas_quantidades = []
        saidas_ids = []
        saidas_finalizado = []

        saidas_queryset = semeadura.saidas.filter(finalizado=False)

        for saida in saidas_queryset:
            saidas_data.append(saida.data_saida.strftime('%d/%m/%Y'))
            saidas_quantidades.append(str(saida.quantidade_saidas))
            saidas_ids.append(saida.id)
            saidas_finalizado.append(saida.finalizado)

        saidas_data = saidas_data if saidas_data else [""]
        saidas_quantidades = saidas_quantidades if saidas_quantidades else [""]
        saidas_ids = saidas_ids if saidas_ids else [""]

        saidas.append({
            'semeadura_id': semeadura.id,
            'numero_muda': semeadura.numero_muda,
            'data_semeia': semeadura.data_semeia,
            'nome_popular': semeadura.lote.especie.nome_popular,
            'especies': semeadura.lote.especie.especies,
            'ultima_data_saida': semeadura.ultima_data_saida,
            'total_saida': semeadura.total_saida,
            'total_repique': int(semeadura.total_repique) if semeadura.total_repique is not None else 0,
            'total_mortalidade_estufa': semeadura.total_mortalidade_estufa,
            'saida_venda': venda,
            'saida_dates': saidas_data,
            'saida_quantities': saidas_quantidades,
            'saida_ids': saidas_ids,
            'finalizado': saidas_finalizado,
            'estimativa_minima': semeadura.lote.estimativa_minima,
            'estimativa_maxima': semeadura.lote.estimativa_maxima,
            'estimativa_media': semeadura.lote.estimativa_minima,
            'qtd_sementes_utilizada': semeadura.qtd_sementes_utilizada,
            'total_quantidade_selecao': semeadura.total_quantidade_selecao,
            'total_qtd_especie': semeadura.total_venda,
            'diferenca_qtd': diferenca_qtd,
        })

    return {'semeaduras': semeaduras, 'saidas': saidas}

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

    user_info = get_user_info(request.user.id)
    saidas_info = get_lista_saidas_data()

    if request.method == 'POST':
        form = ProtocoloForm(request.POST)
        semeadura_ids = [saida['semeadura_id'] for saida in saidas_info['saidas']]
        
        # Filtrar seleções que estão marcadas como venda
        selecoes_venda = Selecao.objects.filter(semeadura_id__in=semeadura_ids, venda=True)
        semeadura_ids_venda = selecoes_venda.values_list('semeadura_id', flat=True).distinct()
        
        semeadura_choices = Semeadura.objects.filter(id__in=semeadura_ids_venda)
        for semeadura in semeadura_choices:
            qtd_especie = ProtocoloSemeadura.objects.filter(semeadura=semeadura).aggregate(total_qtd_especie=Sum('qtd_especie'))['total_qtd_especie'] or 0
            quantidade_selecao = Selecao.objects.filter(semeadura=semeadura, venda=True).aggregate(total_quantidade_selecao=Sum('quantidade_selecao'))['total_quantidade_selecao'] or 0
            semeadura.diferenca_qtd = quantidade_selecao
            print(f"[DEBUG] Semeadura ID: {semeadura.id}, Quantidade Selecao: {quantidade_selecao}, Qtd Especie: {qtd_especie}, Diferenca Qtd: {semeadura.diferenca_qtd}")  # Log de depuração

        form.set_semeadura_choices(semeadura_choices)

        if form.is_valid():
            protocolo_data = form.cleaned_data.copy()
            protocolo_data['cliente_fisico'] = protocolo_data['cliente_fisico'].id if protocolo_data['cliente_fisico'] else None
            protocolo_data['cliente_empresa'] = protocolo_data['cliente_empresa'].id if protocolo_data['cliente_empresa'] else None
            protocolo_data['semeaduras'] = [semeadura.id for semeadura in protocolo_data['semeaduras']]

            # Serialize 'data_saida_protocolo' to a string
            if 'data_saida_protocolo' in protocolo_data and protocolo_data['data_saida_protocolo']:
                protocolo_data['data_saida_protocolo'] = protocolo_data['data_saida_protocolo'].isoformat()

            request.session['protocolo_data'] = protocolo_data
            return redirect('step4_protocolo')
    else:
        form = ProtocoloForm()
        semeadura_ids = [saida['semeadura_id'] for saida in saidas_info['saidas']]
        
        # Filtrar seleções que estão marcadas como venda
        selecoes_venda = Selecao.objects.filter(semeadura_id__in=semeadura_ids, venda=True)
        semeadura_ids_venda = selecoes_venda.values_list('semeadura_id', flat=True).distinct()
        
        semeadura_choices = Semeadura.objects.filter(id__in=semeadura_ids_venda)
        for semeadura in semeadura_choices:
            qtd_especie = ProtocoloSemeadura.objects.filter(semeadura=semeadura).aggregate(total_qtd_especie=Sum('qtd_especie'))['total_qtd_especie'] or 0
            quantidade_selecao = Selecao.objects.filter(semeadura=semeadura, venda=True).aggregate(total_quantidade_selecao=Sum('quantidade_selecao'))['total_quantidade_selecao'] or 0
            semeadura.diferenca_qtd = quantidade_selecao - qtd_especie
            print(f"[DEBUG] Semeadura ID: {semeadura.id}, Quantidade Selecao: {quantidade_selecao}, Qtd Especie: {qtd_especie}, Diferenca Qtd: {semeadura.diferenca_qtd}")  # Log de depuração

        form.set_semeadura_choices(semeadura_choices)

    context = {
        'form': form,
        'user_info': user_info,
        'saidas_info': saidas_info['saidas'],
        'semeadura_choices': semeadura_choices,
    }

    return render(request, 'protocolos/cadastro_protocolo.html', context)

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

    user_info = get_user_info(request.user.id)
    protocolo_data = request.session.get('protocolo_data')
    if not protocolo_data:
        return redirect('cadastro_protocolo')

    # Deserialize 'data_saida_protocolo' back to a date object
    if 'data_saida_protocolo' in protocolo_data and protocolo_data['data_saida_protocolo']:
        protocolo_data['data_saida_protocolo'] = datetime.strptime(protocolo_data['data_saida_protocolo'], '%Y-%m-%d').date()

    if not protocolo_data:
        return redirect('cadastro_protocolo')

    semeaduras_ids = protocolo_data.pop('semeaduras')
    semeaduras = Semeadura.objects.filter(id__in=semeaduras_ids)

    saidas_data = get_lista_saidas_data()

    semeaduras = saidas_data['semeaduras'].filter(id__in=semeaduras_ids)

    saidas_dict = {saida['semeadura_id']: saida['diferenca_qtd'] for saida in saidas_data['saidas']}

    for semeadura in semeaduras:
        qtd_especie = ProtocoloSemeadura.objects.filter(semeadura=semeadura).aggregate(total_qtd_especie=Sum('qtd_especie'))['total_qtd_especie'] or 0
        quantidade_selecao = Selecao.objects.filter(semeadura=semeadura, venda=True).aggregate(total_quantidade_selecao=Sum('quantidade_selecao'))['total_quantidade_selecao'] or 0
        semeadura.diferenca_qtd = quantidade_selecao - qtd_especie

    if request.method == 'POST':
        errors = []
        try:
            with transaction.atomic():
                for semeadura in semeaduras:
                    qtd_especie_str = request.POST.get(f'qtd_especie_{semeadura.id}', '0')
                    categoria = request.POST.get(f'categoria_{semeadura.id}')
                    if not categoria:
                        errors.append(f"Categoria não informada para a semeadura ID {semeadura.id}.")
                        continue

                    valor_unit_str = request.POST.get(f'valor_unit_{semeadura.id}', '0')

                    try:
                        qtd_especie = Decimal(qtd_especie_str)
                        valor_unit = Decimal(valor_unit_str)
                        if qtd_especie <= 0 or valor_unit < 0:
                            raise InvalidOperation
                    except InvalidOperation:
                        errors.append(f"Quantidade de espécie ou valor unitário inválido para a semeadura ID {semeadura.id}.")
                        continue

                    total_quantidade_selecao = Selecao.objects.filter(semeadura=semeadura).aggregate(total_quantidade_selecao=Sum('quantidade_selecao'))['total_quantidade_selecao'] or 0
                    total_qtd_especie = ProtocoloSemeadura.objects.filter(semeadura=semeadura).aggregate(total_qtd_especie=Sum('qtd_especie'))['total_qtd_especie'] or 0
                    
                    if total_qtd_especie + qtd_especie > total_quantidade_selecao:
                        errors.append(
                            f"A Espécie: {semeadura.lote.especie.nome_popular} + {semeadura.lote.especie.especies}.\n"
                            f"Número de Muda: {semeadura.numero_muda}.\n"
                            f"Não pode ser maior que a quantidade de seleção ({semeadura.diferenca_qtd})."
                        )
                        continue

                observacao = request.POST.get('observacao', '')

                if errors:
                    for error in errors:
                        messages.error(request, error)
                    return redirect('step4_protocolo')

                protocolo = Protocolo(
                    tipo_cliente=protocolo_data['tipo_cliente'],
                    cliente_fisico_id=protocolo_data['cliente_fisico'],
                    cliente_empresa_id=protocolo_data['cliente_empresa'],
                    num_protocolo=protocolo_data['num_protocolo'],
                    referente_nf=protocolo_data['referente_nf'],
                    tipo_pagamento=protocolo_data['tipo_pagamento'],
                    num_pedido=protocolo_data['num_pedido'],
                    destino_muda=protocolo_data['destino_muda'],
                    placa_veiculo=protocolo_data['placa_veiculo'],
                    resp_recebimento=protocolo_data['resp_recebimento'],
                    inscricao_estadual=protocolo_data['inscricao_estadual'],
                    produtor=protocolo_data['produtor'],
                    renasem_produtor=protocolo_data['renasem_produtor'],
                    resp_tecnico=protocolo_data['resp_tecnico'],
                    renasem_tecnico=protocolo_data['renasem_tecnico'],
                    data_saida_protocolo=protocolo_data['data_saida_protocolo'],
                    observacao=observacao
                )
                protocolo.save()

                for semeadura_id in semeaduras_ids:
                    ProtocoloSemeadura.objects.get_or_create(protocolo=protocolo, semeadura_id=semeadura_id)

                for semeadura in semeaduras:
                    qtd_especie = Decimal(request.POST.get(f'qtd_especie_{semeadura.id}', '0'))
                    valor_unit = Decimal(request.POST.get(f'valor_unit_{semeadura.id}', '0'))
                    valor_total = qtd_especie * valor_unit

                    ProtocoloSemeadura.objects.update_or_create(
                        protocolo=protocolo,
                        semeadura=semeadura,
                        defaults={
                            'categoria': request.POST.get(f'categoria_{semeadura.id}'),
                            'qtd_especie': qtd_especie,
                            'valor_unit': valor_unit,
                            'valor_total': valor_total,
                            'data_venda': request.POST.get(f'data_venda_{semeadura.id}')
                        }
                    )

                Selecao.objects.filter(venda=True).update(venda=False)

                messages.success(request, "Dados adicionais cadastrados com sucesso.")
                return redirect('lista_de_protocolos')

        except Exception as e:
            logger.error(f"Erro ao processar o protocolo: {e}")
            messages.error(request, "Ocorreu um erro ao processar o protocolo. Tente novamente.")
            return redirect('step4_protocolo')

    else:
        formset = ProtocoloSemeaduraFormSet(queryset=ProtocoloSemeadura.objects.none())

    context = {
        'formset': formset,
        'semeaduras': semeaduras,
        'user_info': user_info,
    }
    return render(request, 'protocolos/step4_protocolo.html', context)

def editar_protocolo(request, protocolo_id):
    if not request.user.is_authenticated:
        return redirect('index')

    protocolo = get_object_or_404(Protocolo, id=protocolo_id)
    user_info = get_user_info(request.user.id)
    saidas_info = get_lista_saidas_data()

    ProtocoloSemeaduraFormSet = inlineformset_factory(
        Protocolo, ProtocoloSemeadura, form=ProtocoloSemeaduraForm, extra=0, can_delete=True
    )

    if request.method == 'POST':
        formset = ProtocoloSemeaduraFormSet(request.POST, instance=protocolo)
        semeadura_ids = [saida['semeadura_id'] for saida in saidas_info['saidas']]
        semeadura_choices = Semeadura.objects.filter(id__in=semeadura_ids)

        # Não permitir edição de semeadura
        for form in formset.forms:
            if 'semeadura' in form.fields:
                form.fields['semeadura'].queryset = semeadura_choices
                form.fields['semeadura'].disabled = True

        if formset.is_valid():
            try:
                with transaction.atomic():
                    form_with_error = None
                    for form in formset.forms:
                        semeadura = form.instance.semeadura
                        qtd_especie = form.cleaned_data.get('qtd_especie', 0)

                        total_quantidade_selecao = Selecao.objects.filter(semeadura=semeadura).aggregate(total_quantidade_selecao=Sum('quantidade_selecao'))['total_quantidade_selecao'] or 0
                        total_qtd_especie = ProtocoloSemeadura.objects.filter(semeadura=semeadura).exclude(id=form.instance.id).aggregate(total_qtd_especie=Sum('qtd_especie'))['total_qtd_especie'] or 0
                        
                        # Verificar se a nova quantidade de espécie excede o limite permitido
                        if total_qtd_especie + qtd_especie > total_quantidade_selecao:
                            # Adiciona um erro ao formulário
                            form.add_error('qtd_especie', f"A quantidade de espécie ({total_qtd_especie + qtd_especie}) não pode ser maior que a quantidade de seleção ({semeadura.diferenca_qtd}).")
                            form_with_error = form

                    if form_with_error:
                        # Não salva o formset, pois há erro
                        messages.error(request, "Erro ao validar o formulário. Verifique os campos destacados.")
                    else:
                        formset.save()
                        messages.success(request, "Protocolo atualizado com sucesso.")
                        return redirect('lista_de_protocolos')

            except Exception as e:
                logger.error(f"Erro ao processar o protocolo: {e}")
                messages.error(request, "Ocorreu um erro ao processar o protocolo. Tente novamente.")
        else:
            messages.error(request, "Erro ao validar o formulário. Verifique os dados e tente novamente.")
    else:
        formset = ProtocoloSemeaduraFormSet(instance=protocolo)
        semeadura_ids = [saida['semeadura_id'] for saida in saidas_info['saidas']]
        semeadura_choices = Semeadura.objects.filter(id__in=semeadura_ids)

        # Não permitir edição de semeadura
        for form in formset.forms:
            if 'semeadura' in form.fields:
                form.fields['semeadura'].queryset = semeadura_choices
                form.fields['semeadura'].disabled = True

    # Calcular a diferenca_qtd para cada semeadura relacionada
    for form in formset.forms:
        semeadura = form.instance.semeadura
        if semeadura:
            qtd_especie = ProtocoloSemeadura.objects.filter(semeadura=semeadura).aggregate(total_qtd_especie=Sum('qtd_especie'))['total_qtd_especie'] or 0
            quantidade_selecao = Selecao.objects.filter(semeadura=semeadura).aggregate(total_quantidade_selecao=Sum('quantidade_selecao'))['total_quantidade_selecao'] or 0
            # Adicionar a diferença ao formulário
            form.diferenca_qtd = quantidade_selecao - qtd_especie

    context = {
        'formset': formset,
        'user_info': user_info,
        'protocolo': protocolo,
        'semeadura_choices': semeadura_choices,
        'saidas_info': saidas_info,
    }

    return render(request, 'protocolos/editar_protocolo.html', context)

def adicionar_muda(request, protocolo_id):
    if not request.user.is_authenticated:
        return redirect('index')

    protocolo = get_object_or_404(Protocolo, id=protocolo_id)
    user_info = get_user_info(request.user.id)

    saidas_info = get_lista_saidas_data()
    semeadura_ids = [saida['semeadura_id'] for saida in saidas_info['saidas']]
    
    # Filtrar selecoes que estão marcadas como venda e que não estão já adicionadas ao protocolo
    selecoes_venda = Selecao.objects.filter(semeadura_id__in=semeadura_ids, venda=True)
    semeadura_ids_venda = selecoes_venda.values_list('semeadura_id', flat=True).distinct()
    mudas_adicionadas = ProtocoloSemeadura.objects.filter(protocolo=protocolo).values_list('semeadura_id', flat=True)
    
    semeadura_choices = Semeadura.objects.filter(id__in=semeadura_ids_venda).exclude(id__in=mudas_adicionadas)

    if request.method == 'POST':
        form = ProtocoloSemeaduraForm(request.POST)
        form.set_semeadura_choices(semeadura_choices)
        if form.is_valid():
            nova_muda = form.save(commit=False)
            nova_muda.protocolo = protocolo
            qtd_especie = form.cleaned_data.get('qtd_especie', 0)
            semeadura = nova_muda.semeadura

            total_quantidade_selecao = Selecao.objects.filter(semeadura=semeadura).aggregate(total_quantidade_selecao=Sum('quantidade_selecao'))['total_quantidade_selecao'] or 0
            total_qtd_especie = ProtocoloSemeadura.objects.filter(semeadura=semeadura).aggregate(total_qtd_especie=Sum('qtd_especie'))['total_qtd_especie'] or 0

            # Verificar se a nova quantidade de espécie excede o limite permitido
            if total_qtd_especie + qtd_especie > total_quantidade_selecao:
                messages.error(request, f"A quantidade de espécie ({total_qtd_especie + qtd_especie}) não pode ser maior que a quantidade de seleção ({total_quantidade_selecao}) para a semeadura ID {semeadura.id}.")
                return JsonResponse({'success': False, 'html': render_to_string('protocolos/form_adicionar_muda.html', {'form': form, 'protocolo': protocolo}, request=request)})

            try:
                nova_muda.save()
                return JsonResponse({'success': True})
            except IntegrityError:
                return JsonResponse({'success': False, 'html': render_to_string('protocolos/form_adicionar_muda.html', {'form': form, 'protocolo': protocolo}, request=request)})
        else:
            return JsonResponse({'success': False, 'html': render_to_string('protocolos/form_adicionar_muda.html', {'form': form, 'protocolo': protocolo}, request=request)})
    else:
        form = ProtocoloSemeaduraForm()
        form.set_semeadura_choices(semeadura_choices)
        return render(request, 'protocolos/form_adicionar_muda.html', {'form': form, 'protocolo': protocolo})

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

    user_info = get_user_info(request.user.id)

    # Filtrar protocolos semeaduras não finalizados
    protocolos_semeaduras = ProtocoloSemeadura.objects.select_related('protocolo', 'semeadura').filter(
        protocolo__id__isnull=False, 
        protocolo__finalizado=False  # Filtrar apenas protocolos abertos
    )

    # Agrupar os dados por protocolo não finalizado
    grouped_data = {}
    for ps in protocolos_semeaduras:
        protocolo_id = ps.protocolo.id
        if protocolo_id not in grouped_data:
            cliente_nome = ps.protocolo.cliente_fisico.nome_completo if ps.protocolo.tipo_cliente == 'F' else ps.protocolo.cliente_empresa.nome_fantasia
            grouped_data[protocolo_id] = {
                'numero_protocolo': ps.protocolo.id,
                'data_criacao': ps.protocolo.data_criacao,
                'quantidade_mudas': 0,
                'cliente_nome': cliente_nome,
                'info_form': ProtocoloInfoForm(instance=ps.protocolo),
                'mudas_form': ProtocoloSemeaduraForm(instance=ps)
            }
        grouped_data[protocolo_id]['quantidade_mudas'] += ps.qtd_especie if ps.qtd_especie else 0

    # Pegar os protocolos finalizados e agrupar de maneira similar
    protocolos_finalizados_semeaduras = ProtocoloSemeadura.objects.select_related('protocolo', 'semeadura').filter(
        protocolo__finalizado=True  # Filtrar apenas protocolos finalizados
    )

    grouped_finalizados = {}
    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.id,
                'data_criacao': ps.protocolo.data_criacao,
                'quantidade_mudas': 0,
                'cliente_nome': cliente_nome,
                'info_form': ProtocoloInfoForm(instance=ps.protocolo),
                'mudas_form': ProtocoloSemeaduraForm(instance=ps)
            }
        grouped_finalizados[protocolo_id]['quantidade_mudas'] += ps.qtd_especie if ps.qtd_especie else 0

    context = {
        'grouped_data': grouped_data.values(),
        'grouped_finalizados': grouped_finalizados.values(),  # Passar os protocolos finalizados agrupados ao template
        'user_info': user_info,
    }

    return render(request, 'protocolos/lista_de_protocolos.html', context)

def editar_info(request, protocolo_id):
    if not request.user.is_authenticated:
        return redirect('index')

    user_info = get_user_info(request.user.id)
    protocolo = get_object_or_404(Protocolo, id=protocolo_id)

    if request.method == 'POST':
        form = ProtocoloInfoForm(request.POST, instance=protocolo)
        if form.is_valid():
            form.save()
            return JsonResponse({'success': True})
        else:
            # Passa 'protocolo' no contexto
            html = render_to_string('protocolos/form_editar_info.html', {'form': form, 'protocolo': protocolo}, request=request)
            return JsonResponse({'success': False, 'html': html})
    else:
        form = ProtocoloInfoForm(instance=protocolo)
        return render(request, 'protocolos/form_editar_info.html', {'form': form, 'protocolo': protocolo})

def editar_mudas(request, protocolo_id):
    if not request.user.is_authenticated:
        return redirect('index')

    user_info = get_user_info(request.user.id)
    protocolo = get_object_or_404(Protocolo, id=protocolo_id)
    protocolo_semeaduras = ProtocoloSemeadura.objects.filter(protocolo=protocolo)

    if request.method == 'POST':
        for ps in protocolo_semeaduras:
            form = ProtocoloSemeaduraForm(request.POST, instance=ps, prefix=f'form-{ps.id}')
            if form.is_valid():
                form.save()
            else:
                messages.error(request, f"Erro ao atualizar as informações da muda {ps.id}.")
                # Adicione esta linha para depuração
                print(form.errors)
        messages.success(request, "Informações das mudas atualizadas com sucesso.")
        return redirect('lista_de_protocolos')
    else:
        form_list = [ProtocoloSemeaduraForm(instance=ps, prefix=f'form-{ps.id}') for ps in protocolo_semeaduras]

    context = {
        'form_list': form_list,
        'protocolo': protocolo,
        'user_info': user_info,
    }

    return render(request, 'protocolos/editar_mudas.html', context)

def cliente_info(request, tipo, cliente_id):
    if tipo == 'fisico':
        cliente = ClientesModels.objects.get(id=cliente_id)
        data = {
            'nome': cliente.nome_completo,
            'cpf': cliente.cpf,
            'email': cliente.email,
            'uf': cliente.uf,
            'status': cliente.status,
            'cidade': cliente.cidade,
            'endereco': cliente.endereco,
            'numero_casa': cliente.numero_casa,
            'bairro': cliente.bairro,
            'complemento': cliente.complemento,
            'cep': cliente.cep,
            'telefone_celular': cliente.telefone_celular,
            'telefone_residencial': cliente.telefone_residencial,
            'inscricao_estadual': cliente.inscricao_estadual,
        }
    elif tipo == 'empresa':
        cliente = EmpresasModels.objects.get(id=cliente_id)
        data = {
            'nome': cliente.nome_fantasia,
            'cnpj': cliente.cnpj,
            'inscricao_estadual': cliente.inscricao_estadual,
            'razao_social': cliente.razao_social,
            'email': cliente.email,
            'uf': cliente.uf,
            'cidade': cliente.cidade,
            'endereco': cliente.endereco,
            'bairro': cliente.bairro,
            'complemento': cliente.complemento,
            'cep': cliente.cep,
            'telefone_celular': cliente.telefone_celular,
            'telefone_residencial': cliente.telefone_residencial,
            'nome_responsavel': cliente.nome_responsavel,
            'contato_responsavel': cliente.contato_responsavel,
        }
    else:
        data = {}
    
    return JsonResponse(data)

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

    user_info = get_user_info(request.user.id)
    # Consultar todos os registros do modelo Protocolo
    protocolos = Protocolo.objects.all()
    
    # Consultar todos os registros do modelo ProtocoloSemeadura
    protocolos_semeaduras = ProtocoloSemeadura.objects.all()

    context = {
        'protocolos': protocolos,
        'protocolos_semeaduras': protocolos_semeaduras,
        'user_info': user_info,
    }

    return render(request, 'protocolos/listar_protocolos.html', context)

def excluir_protocolo(request, protocolo_id):
    if not request.user.is_authenticated:
        return redirect('index')

    protocolo = get_object_or_404(Protocolo, id=protocolo_id)
    
    # Restaurar os valores no modelo Selecao
    
        

    protocolo.delete()
    messages.success(request, "Protocolo excluído com sucesso e os valores foram restaurados.")

    return redirect('lista_de_protocolos')

def finalizar_protocolo(request, protocolo_id):
    if not request.user.is_authenticated:
        return redirect('index')

    protocolo = get_object_or_404(Protocolo, id=protocolo_id)
    protocolo.finalizado = True  # Marcar o protocolo como finalizado
    protocolo.save()  # Salvar a mudança no banco de dados

    messages.success(request, "Protocolo finalizado com sucesso.")
    return redirect('lista_de_protocolos')

def protocolo_pdf(request, protocolo_id):
    protocolo = get_object_or_404(Protocolo, id=protocolo_id)
    protocolo_semeaduras = ProtocoloSemeadura.objects.filter(protocolo=protocolo)

    numero_protocolo = protocolo.num_protocolo or protocolo.id

    if protocolo.data_saida_protocolo:
        data_emissao = protocolo.data_saida_protocolo.strftime("%d/%m/%Y")
    else:
        data_emissao = datetime.now().strftime("%d/%m/%Y")

    cliente_nome = protocolo.cliente_fisico.nome_completo if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.nome_fantasia
    cliente_tel = protocolo.cliente_fisico.telefone_celular if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.telefone_celular
    cliente_ie = protocolo.cliente_fisico.inscricao_estadual if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.inscricao_estadual
    cliente_cnpj_cpf = protocolo.cliente_fisico.cpf if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.cnpj
    cliente_endereco = protocolo.cliente_fisico.endereco if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.endereco
    cliente_cep = protocolo.cliente_fisico.cep if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.cep
    cliente_cidade = protocolo.cliente_fisico.cidade if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.cidade
    tipo_pagamento = protocolo.get_tipo_pagamento_display() or ''
    cliente_email = protocolo.cliente_fisico.email if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.email
    num_pedido = protocolo.num_pedido or ''
    destino_muda = protocolo.destino_muda or ''
    placa_veiculo = protocolo.placa_veiculo or ''
    resp_recebimento = protocolo.resp_recebimento or ''

    # Criar um PDF usando ReportLab
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = f'attachment; filename="protocolo_{numero_protocolo}.pdf"'

    margem_total = 0
    buffer = BytesIO()
    doc = SimpleDocTemplate(buffer, pagesize=letter, leftMargin=margem_total, rightMargin=margem_total,
                            topMargin=margem_total, bottomMargin=margem_total)

    elements = []
    elements.append(Spacer(1, margem_total))
    styles = getSampleStyleSheet()
    styles["Normal"].fontName = "Helvetica"
    styles["Normal"].fontSize = 8  # Define o tamanho da fonte para 8px
    bold_style = styles["Normal"].clone('bold_style')
    bold_style.fontName = 'Helvetica-Bold'
    bold_style.fontSize = 8  # Define o tamanho da fonte para 8px
    lightgray = colors.Color(0.9, 0.9, 0.9)

    imagem_path = staticfiles_storage.path('assets/img/logo-ama-footer.png')
    imagem = Image(imagem_path)
    imagem.drawHeight = 70
    imagem.drawWidth = 70

    # Dados da tabela
    data = [
        ['PROTOCOLO DE SAÍDA E VENDA DE MUDAS', '', '', ''],
        [imagem, '', Paragraph(f"PROTOCOLO N°: {numero_protocolo}", bold_style), Paragraph(f"DATA DE SAIDA: {data_emissao}", bold_style)],
        ['', '', Paragraph(f"REFERENTE NF N°: {protocolo.referente_nf}", bold_style), Paragraph(f"DATA DE RECEBIMENTO:", bold_style)],
        ['', '', Paragraph(f"ASSINATURA CLIENTE:", bold_style), ''],
    ]

    # Estilo da tabela
    style = TableStyle([
        ('FONTNAME', (0, 0), (-1, -1), 'Helvetica-Bold'),
        ('FONTSIZE', (0, 0), (-1, -1), 8),  # Define o tamanho da fonte para 8px
        ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ('ALIGN', (0, 0), (1, 1), 'CENTER'),
        ('BACKGROUND', (0, 0), (-1, 0), colors.lightgrey),
        ('SPAN', (0, 0), (-1, 0)),
        ('SPAN', (0, 1), (0, 3)),  # Faz a imagem ocupar todas as linhas necessárias
        ('SPAN', (2, 2), (2, 2)),
        ('SPAN', (2, 3), (3, 3)),  # Garante que assinatura ocupe a linha completa abaixo
        ('VALIGN', (2, 3), (3, 3), 'TOP'),
        ('ALIGN', (2, 3), (3, 3), 'LEFT'),
    ])

    tabela = Table(data, style=style, colWidths=[100, 0, 250, 250], rowHeights=[20, 20, 20, 30])  # Ajuste da largura e altura das células
    elements.append(tabela)

    separators = [['']]
    separatorsstyle = TableStyle([])
    sep = Table(separators, style=separatorsstyle, rowHeights=[10])
    elements.append(sep)

    data1 = [
        [Paragraph(f"<b>CLIENTE:</b> {cliente_nome}", styles["Normal"]), Paragraph(f"<b>TEL:</b> {cliente_tel or ''}", styles["Normal"]), Paragraph(f"<b>PEDIDO COMPRA N°:</b> {num_pedido}", styles["Normal"])],
        [Paragraph(f"<b>INSCRIÇÃO ESTADUAL:</b> {cliente_ie or ''}", styles["Normal"]), Paragraph(f"<b>CPF/CNPJ:</b> {cliente_cnpj_cpf or ''}", styles["Normal"]), Paragraph(f"<b>CIDADE:</b> {cliente_cidade or ''}", styles["Normal"])],
        [Paragraph(f"<b>ENDEREÇO:</b> {cliente_endereco or ''}", styles["Normal"]), Paragraph(f"<b>CEP:</b> {cliente_cep or ''}", styles["Normal"])],
    ]
    style1 = TableStyle([
        ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ('FONTSIZE', (0, 0), (-1, -1), 8),  # Define o tamanho da fonte para 8px
        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
    ])
    table1 = Table(data1, style=style1, rowHeights=[15, 15, 15])  # Ajuste da altura das linhas
    elements.append(table1)

    separators = [['']]
    separatorsstyle = TableStyle([])
    sep = Table(separators, style=separatorsstyle, rowHeights=[10])
    elements.append(sep)

    data2 = [
        [Paragraph("DESTINO MUDAS:", bold_style), Paragraph(destino_muda, styles["Normal"]), '', ''],
    ]
    style2 = TableStyle([
        ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ('SPAN', (1, 0), (3, 0)),
        ('BACKGROUND', (0, 0), (0, 0), lightgray),
        ('FONTSIZE', (0, 0), (-1, -1), 8),  # Define o tamanho da fonte para 8px
        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
    ])
    table2 = Table(data2, style=style2, rowHeights=[15])  # Ajuste da altura das linhas
    elements.append(table2)

    separators = [['']]
    sep = Table(separators, style=separatorsstyle, rowHeights=[10])
    elements.append(sep)

    data4 = [
        [Paragraph("N°", bold_style), Paragraph("Nome cientifico:", bold_style), Paragraph("Nome vulgar:", bold_style),
         Paragraph("N° lote:", bold_style), Paragraph("Quant. p/ espécie:", bold_style), Paragraph("Valor uni:", bold_style),
         Paragraph("Total:", bold_style)]
    ]
    for index, ps in enumerate(protocolo_semeaduras, start=1):
        semeadura = ps.semeadura
        row_data = [
            Paragraph(f"{index}", styles["Normal"]),
            Paragraph(semeadura.lote.especie.especies or '', styles["Normal"]),
            Paragraph(semeadura.lote.especie.nome_popular or '', styles["Normal"]),
            Paragraph(semeadura.lote.numero_lote or '', styles["Normal"]),
            Paragraph(str(ps.qtd_especie or 0), styles["Normal"]),
            Paragraph(format_currency(ps.valor_unit or 0, 'BRL', locale='pt_BR'), styles["Normal"]),
            Paragraph(format_currency(ps.valor_total or 0, 'BRL', locale='pt_BR'), styles["Normal"]),
        ]
        data4.append(row_data)

    total_mudas = sum(ps.qtd_especie for ps in protocolo_semeaduras)
    total_valor = sum(ps.valor_total for ps in protocolo_semeaduras)
    soma_total_row = [
        Paragraph("TOTAL DE MUDAS E VALORES", bold_style), '', '', '', Paragraph(f"{total_mudas}", bold_style), '',
        Paragraph(format_currency(total_valor, 'BRL', locale='pt_BR'), bold_style)
    ]
    data4.append(soma_total_row)

    style4 = TableStyle([
        ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ('BACKGROUND', (0, 0), (-1, 0), lightgray),
        ('BACKGROUND', (0, 1), (-1, -2), colors.white),
        ('FONTSIZE', (0, 0), (-1, -1), 8),  # Define o tamanho da fonte para 8px
        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
        ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
        ('SPAN', (0, -1), (2, -1)),
    ])
    col_widths = [25, 160, 160, 70, 50, 60, 70]
    
    table4 = Table(data4, colWidths=col_widths, rowHeights=[22] * len(data4))  # Ajuste da altura das linhas
    table4.setStyle(style4)
    elements.append(table4)

    separators = [['']]
    sep = Table(separators, style=separatorsstyle, rowHeights=[10])
    elements.append(sep)

    # Dados da tabela de observação
    observacao_data = [
        [Paragraph("OBSERVAÇÃO:", bold_style)],
        [Paragraph(protocolo.observacao or '', styles["Normal"])]
    ]

    # Estilo da tabela de observação
    observacao_style = TableStyle([
        ('FONTNAME', (0, 0), (-1, -1), 'Helvetica-Bold'),
        ('FONTSIZE', (0, 0), (-1, -1), 8),  # Define o tamanho da fonte para 8px
        ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
        ('VALIGN', (0, 0), (-1, -1), 'TOP'),
    ])

    observacao_table = Table(observacao_data, style=observacao_style, colWidths=[595], rowHeights=[15, 50])
    elements.append(observacao_table)

    observacao = "Obs: O prazo máximo para a restituição das caixas pertencentes ao viveiro AMA é de sete dias. Os materiais pertencentes ao viveiro devem ser conservados e devolvidos na exata quantidade enviada, sendo de responsabilidade do cliente assegurar a integralidade deste processo. Na ausência da devolução, será aplicada uma taxa de R$ 70,00 por cada unidade de caixa não restituída."
    paragrafo_observacao_style = ParagraphStyle(name='Observacao', spaceBefore=5, fontSize=8)  # Define o tamanho da fonte para 8px
    paragrafo_observacao = Paragraph(observacao, paragrafo_observacao_style)
    paragrafo_observacao._leading = 5
    elements.append(paragrafo_observacao)


    doc.build(elements)
    pdf = buffer.getvalue()
    buffer.close()
    response.write(pdf)
    return response

def protocolo_pdf_sem_monetario(request, protocolo_id):
    protocolo = get_object_or_404(Protocolo, id=protocolo_id)
    protocolo_semeaduras = ProtocoloSemeadura.objects.filter(protocolo=protocolo)

    numero_protocolo = protocolo.num_protocolo or protocolo.id

    if protocolo.data_saida_protocolo:
        data_emissao = protocolo.data_saida_protocolo.strftime("%d/%m/%Y")
    else:
        data_emissao = datetime.now().strftime("%d/%m/%Y")

    cliente_nome = protocolo.cliente_fisico.nome_completo if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.nome_fantasia
    cliente_tel = protocolo.cliente_fisico.telefone_celular if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.telefone_celular
    cliente_ie = protocolo.cliente_fisico.inscricao_estadual if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.inscricao_estadual
    cliente_cnpj_cpf = protocolo.cliente_fisico.cpf if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.cnpj
    cliente_endereco = protocolo.cliente_fisico.endereco if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.endereco
    cliente_cep = protocolo.cliente_fisico.cep if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.cep
    cliente_cidade = protocolo.cliente_fisico.cidade if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.cidade
    tipo_pagamento = protocolo.get_tipo_pagamento_display() or ''
    cliente_email = protocolo.cliente_fisico.email if protocolo.tipo_cliente == 'F' else protocolo.cliente_empresa.email
    num_pedido = protocolo.num_pedido or ''
    destino_muda = protocolo.destino_muda or ''
    placa_veiculo = protocolo.placa_veiculo or ''
    resp_recebimento = protocolo.resp_recebimento or ''

    # Criar um PDF usando ReportLab
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = f'attachment; filename="protocolo_{numero_protocolo}.pdf"'

    margem_total = 0
    buffer = BytesIO()
    doc = SimpleDocTemplate(buffer, pagesize=letter, leftMargin=margem_total, rightMargin=margem_total,
                            topMargin=margem_total, bottomMargin=margem_total)

    elements = []
    elements.append(Spacer(1, margem_total))
    styles = getSampleStyleSheet()
    styles["Normal"].fontName = "Helvetica"
    styles["Normal"].fontSize = 8  # Define o tamanho da fonte para 8px
    bold_style = styles["Normal"].clone('bold_style')
    bold_style.fontName = 'Helvetica-Bold'
    bold_style.fontSize = 8  # Define o tamanho da fonte para 8px
    lightgray = colors.Color(0.9, 0.9, 0.9)

    imagem_path = staticfiles_storage.path('assets/img/logo-ama-footer.png')
    imagem = Image(imagem_path)
    imagem.drawHeight = 70
    imagem.drawWidth = 70

    # Dados da tabela
    data = [
        ['PROTOCOLO DE SAÍDA E VENDA DE MUDAS', '', '', ''],
        [imagem, '', Paragraph(f"PROTOCOLO N°: {numero_protocolo}", bold_style), Paragraph(f"DATA DE SAIDA: {data_emissao}", bold_style)],
        ['', '', Paragraph(f"REFERENTE NF N°: {protocolo.referente_nf}", bold_style), Paragraph(f"DATA DE RECEBIMENTO:", bold_style)],
        ['', '', Paragraph(f"ASSINATURA CLIENTE:", bold_style), ''],
    ]

    # Estilo da tabela
    style = TableStyle([
        ('FONTNAME', (0, 0), (-1, -1), 'Helvetica-Bold'),
        ('FONTSIZE', (0, 0), (-1, -1), 8),  # Define o tamanho da fonte para 8px
        ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ('ALIGN', (0, 0), (1, 1), 'CENTER'),
        ('BACKGROUND', (0, 0), (-1, 0), colors.lightgrey),
        ('SPAN', (0, 0), (-1, 0)),
        ('SPAN', (0, 1), (0, 3)),  # Faz a imagem ocupar todas as linhas necessárias
        ('SPAN', (2, 2), (2, 2)),
        ('SPAN', (2, 3), (3, 3)),  # Garante que assinatura ocupe a linha completa abaixo
        ('VALIGN', (2, 3), (3, 3), 'TOP'),
        ('ALIGN', (2, 3), (3, 3), 'LEFT'),
    ])

    tabela = Table(data, style=style, colWidths=[100, 0, 250, 250], rowHeights=[20, 20, 20, 30])  # Ajuste da largura e altura das células
    elements.append(tabela)

    separators = [['']]
    separatorsstyle = TableStyle([])
    sep = Table(separators, style=separatorsstyle, rowHeights=[10])
    elements.append(sep)

    data1 = [
        [Paragraph(f"<b>CLIENTE:</b> {cliente_nome}", styles["Normal"]), Paragraph(f"<b>INSCRIÇÃO ESTADUAL:</b> {cliente_ie or ''}", styles["Normal"]), Paragraph(f"<b>PEDIDO COMPRA N°:</b> {num_pedido}", styles["Normal"])],
    ]
    style1 = TableStyle([
        ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ('FONTSIZE', (0, 0), (-1, -1), 8),  # Define o tamanho da fonte para 8px
        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
    ])
    table1 = Table(data1, style=style1, rowHeights=[15])  # Ajuste da altura das linhas
    elements.append(table1)

    separators = [['']]
    separatorsstyle = TableStyle([])
    sep = Table(separators, style=separatorsstyle, rowHeights=[10])
    elements.append(sep)

    data2 = [
        [Paragraph("DESTINO MUDAS:", bold_style), Paragraph(destino_muda, styles["Normal"]), '', ''],
    ]
    style2 = TableStyle([
        ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ('SPAN', (1, 0), (3, 0)),
        ('BACKGROUND', (0, 0), (0, 0), lightgray),
        ('FONTSIZE', (0, 0), (-1, -1), 8),  # Define o tamanho da fonte para 8px
        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
    ])
    table2 = Table(data2, style=style2, rowHeights=[15])  # Ajuste da altura das linhas
    elements.append(table2)

    separators = [['']]
    sep = Table(separators, style=separatorsstyle, rowHeights=[10])
    elements.append(sep)

    data4 = [
        [Paragraph("N°", bold_style), Paragraph("Nome cientifico:", bold_style), Paragraph("Nome vulgar:", bold_style),
         Paragraph("N° lote:", bold_style), Paragraph("Quant. p/ espécie:", bold_style), Paragraph("Valor uni:", bold_style),
         Paragraph("Total:", bold_style)]
    ]
    for index, ps in enumerate(protocolo_semeaduras, start=1):
        semeadura = ps.semeadura
        row_data = [
            Paragraph(f"{index}", styles["Normal"]),
            Paragraph(semeadura.lote.especie.especies or '', styles["Normal"]),
            Paragraph(semeadura.lote.especie.nome_popular or '', styles["Normal"]),
            Paragraph(semeadura.lote.numero_lote or '', styles["Normal"]),
            Paragraph(str(ps.qtd_especie or 0), styles["Normal"]),
        Paragraph('***', styles["Normal"]),  # Exibe o valor unitário como asteriscos
        Paragraph('***', styles["Normal"]),  # Exibe o valor total como asteriscos
        ]
        data4.append(row_data)

    total_mudas = sum(ps.qtd_especie for ps in protocolo_semeaduras)
    total_valor = sum(ps.valor_total for ps in protocolo_semeaduras)
    soma_total_row = [
        Paragraph("TOTAL DE MUDAS E VALORES", bold_style), '', '', '', Paragraph(f"{total_mudas}", bold_style), '',
        '***'  # Exibe o total do valor como asteriscos
    ]
    data4.append(soma_total_row)

    style4 = TableStyle([
        ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ('BACKGROUND', (0, 0), (-1, 0), lightgray),
        ('BACKGROUND', (0, 1), (-1, -2), colors.white),
        ('FONTSIZE', (0, 0), (-1, -1), 8),  # Define o tamanho da fonte para 8px
        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
        ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
        ('SPAN', (0, -1), (2, -1)),
    ])
    col_widths = [25, 160, 160, 70, 50, 60, 70]
    
    table4 = Table(data4, colWidths=col_widths, rowHeights=[22] * len(data4))  # Ajuste da altura das linhas
    table4.setStyle(style4)
    elements.append(table4)

    separators = [['']]
    sep = Table(separators, style=separatorsstyle, rowHeights=[10])
    elements.append(sep)

    # Dados da tabela de observação
    observacao_data = [
        [Paragraph("OBSERVAÇÃO:", bold_style)],
        [Paragraph(protocolo.observacao or '', styles["Normal"])]
    ]

    # Estilo da tabela de observação
    observacao_style = TableStyle([
        ('FONTNAME', (0, 0), (-1, -1), 'Helvetica-Bold'),
        ('FONTSIZE', (0, 0), (-1, -1), 8),  # Define o tamanho da fonte para 8px
        ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
        ('VALIGN', (0, 0), (-1, -1), 'TOP'),
    ])

    observacao_table = Table(observacao_data, style=observacao_style, colWidths=[595], rowHeights=[15, 50])
    elements.append(observacao_table)

    observacao = "Obs: O prazo máximo para a restituição das caixas pertencentes ao viveiro AMA é de sete dias. Os materiais pertencentes ao viveiro devem ser conservados e devolvidos na exata quantidade enviada, sendo de responsabilidade do cliente assegurar a integralidade deste processo. Na ausência da devolução, será aplicada uma taxa de R$ 70,00 por cada unidade de caixa não restituída."
    paragrafo_observacao_style = ParagraphStyle(name='Observacao', spaceBefore=5, fontSize=8)  # Define o tamanho da fonte para 8px
    paragrafo_observacao = Paragraph(observacao, paragrafo_observacao_style)
    paragrafo_observacao._leading = 5
    elements.append(paragrafo_observacao)



    doc.build(elements)
    pdf = buffer.getvalue()
    buffer.close()
    response.write(pdf)
    return response

from django.http import HttpResponse
from io import BytesIO
from datetime import datetime
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Table, TableStyle, Spacer, Image
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from django.contrib.staticfiles.storage import staticfiles_storage


from django.shortcuts import get_object_or_404
from django.http import HttpResponse
from reportlab.lib.pagesizes import letter, landscape
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, Image
from reportlab.lib.units import inch
from io import BytesIO
from django.contrib.staticfiles.storage import staticfiles_storage

def termo_conformidade_pdf(request, protocolo_id):
    protocolo = get_object_or_404(Protocolo, id=protocolo_id)
    protocolo_semeaduras = ProtocoloSemeadura.objects.filter(protocolo=protocolo)

    numero_protocolo = protocolo.num_protocolo or ''
    data_emissao = protocolo.data_criacao.strftime("%d/%m/%Y")

    # Definir os valores fixos
    produtor = "AMA VIVEIRO DE MUDAS LTDA"
    renasem_produtor = "BA-02274/2020"
    resp_tecnico = "EDSON OLIVEIRA FELIPE"
    renasem_tecnico = "BA-2005/2018"

    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = f'attachment; filename="termo_conformidade_{numero_protocolo}.pdf"'

    margem_total = 10
    buffer = BytesIO()
    doc = SimpleDocTemplate(buffer, pagesize=landscape(letter), leftMargin=margem_total, rightMargin=margem_total,
                            topMargin=margem_total, bottomMargin=margem_total)

    elements = []
    styles = getSampleStyleSheet()
    bold_style = styles["Normal"].clone('bold_style')
    bold_style.fontName = 'Helvetica-Bold'
    lightgray = colors.Color(0.9, 0.9, 0.9)

    # Cabeçalho da tabela
    data = [
        ['TERMO DE CONFORMIDADE DE MUDA FLORESTAL'],  # Linha do título centralizado
        ['Produtor:', 'RENASEM n°:', 'Número/Ano/NF:'],  # Primeira linha com os títulos
        [Paragraph(produtor, styles['Normal']), Paragraph(renasem_produtor, styles['Normal']), Paragraph(numero_protocolo, styles['Normal'])],  # Segunda linha com os valores
        ['Responsável Técnico:', 'RENASEM n°:', ''],  # Primeira linha com os títulos
        [Paragraph(resp_tecnico, styles['Normal']), Paragraph(renasem_tecnico, styles['Normal']), '']  # Segunda linha com os valores
    ]

    # Estilo da tabela com borda ao redor do termo de conformidade
    table_style = TableStyle([
        ('FONTNAME', (0, 0), (-1, -1), 'Helvetica-Bold'),
        ('BOX', (0, 1), (-1, -1), 0.5, colors.grey),  # Mantém a borda externa em volta de toda a tabela
        ('INNERGRID', (0, 1), (-2, -1), 0.5, colors.grey),  # Adiciona linhas internas exceto na última coluna (Número/Ano/NF)
        ('INNERGRID', (0, 2), (-3, -3), 0.5, colors.grey),  # Adiciona linhas internas exceto na última coluna (Número/Ano/NF)
        ('BOX', (-1, 1), (-1, 4), 0.5, colors.grey),  # Adiciona uma borda externa ao redor de "Número/Ano/NF"
        ('BACKGROUND', (0, 0), (-1, 0), colors.lightgrey),  # Fundo cinza para o título principal
        ('SPAN', (0, 0), (-1, 0)),  # Mescla todas as colunas para o título "TERMO DE CONFORMIDADE"
        ('BOX', (0, 0), (-1, 0), 1.0, colors.grey),  # Adiciona borda preta ao redor do título "TERMO DE CONFORMIDADE"
        ('ALIGN', (0, 0), (-1, 0), 'CENTER'),  # Centraliza o texto "TERMO DE CONFORMIDADE"
        ('VALIGN', (0, 0), (-1, 0), 'MIDDLE'),  # Centraliza verticalmente o texto do título
    ])

    # Configuração das larguras das colunas
    colWidths = [278, 278, 200]  # Ajuste as larguras conforme necessário para melhor visualização

    # Criação da tabela
    table = Table(data, colWidths=colWidths, style=table_style)
    elements.append(table)

    # Espaço antes da tabela de espécies
    elements.append(Spacer(1, 12))

    # Cabeçalho da tabela de espécies
    species_table_header = [
        ['Nome científico', 'Nome comum', 'Categoria', 'Lote', 'Quantidade de mudas (unidades)']
    ]

    species_data = []
    total_mudas = 0  # Variável para armazenar o total de mudas

    for index, ps in enumerate(protocolo_semeaduras, start=1):
        semeadura = ps.semeadura
        quantidade_mudas = ps.qtd_especie or 0  # Obter a quantidade de mudas
        total_mudas += quantidade_mudas  # Somar ao total

        row_data = [
            Paragraph(semeadura.lote.especie.especies or '', styles["Normal"]),
            Paragraph(semeadura.lote.especie.nome_popular or '', styles["Normal"]),
            Paragraph(ps.categoria or '', styles["Normal"]),
            Paragraph(semeadura.lote.numero_lote or '', styles["Normal"]),
            Paragraph(str(quantidade_mudas), styles["Normal"]),
        ]
        species_data.append(row_data)

    # Adicionar linha do total ao final da tabela
    total_row = [
        '',  # Célula vazia para "Nome científico"
        '',  # Célula vazia para "Nome comum"
        '',  # Célula vazia para "Categoria"
        'Total',  # Rótulo "Total"
        Paragraph(str(total_mudas), styles["Normal"]),  # Total de mudas
    ]
    species_data.append(total_row)

    # Definir largura das colunas de acordo com o exemplo
    species_col_widths = [170, 170, 120, 120, 180]

    # Estilo da tabela de espécies
    species_table_style = TableStyle([
        ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ('BACKGROUND', (0, 0), (-1, 0), lightgray),
        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
        ('FONTNAME', (0, -1), (-1, -1), 'Helvetica-Bold'),  # Colocar a linha do total em negrito
    ])

    species_table = Table(species_table_header + species_data, colWidths=species_col_widths)
    species_table.setStyle(species_table_style)

    # Adicionar a tabela ao documento
    elements.append(species_table)

    # Espaço antes da seção de observação
    elements.append(Spacer(1, 10))

    # Observação final
    observacao = "Atesto que as mudas das espécies florestais foram produzidas de acordo com as normas e padrões estabelecidos pelo Ministério da Agricultura, Pecuária e Abastecimento, pelos quais assumo a responsabilidade pela identidade e qualidade."
    paragrafo_observacao_style = ParagraphStyle(name='Observacao', spaceBefore=20)
    paragrafo_observacao = Paragraph(observacao, paragrafo_observacao_style)
    elements.append(paragrafo_observacao)

    # Espaço antes das assinaturas
    elements.append(Spacer(1, 12))

    # Assinaturas dentro da tabela
    signature_table_data = [
        ['Local e Data', 'Assinatura do Responsável Técnico'],
        ['Assinatura do Recebimento Cliente', '']  # Assinatura do cliente ocupando a primeira coluna da linha
    ]

    # Configurando a tabela com as larguras desejadas
    signature_table = Table(signature_table_data, colWidths=[377, 377])
    signature_table.setStyle(TableStyle([
        ('ALIGN', (0, 0), (-1, -1), 'LEFT'),  # Alinha o texto à esquerda nas células
        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),  # Alinha verticalmente no meio
        ('SPAN', (0, 1), (1, 1)),  # Faz a célula "Assinatura do Recebimento Cliente" ocupar duas colunas
        ('LINEBELOW', (0, 0), (0, 0), 0.5, colors.grey),  # Linha abaixo de "Local e Data"
        ('LINEBELOW', (1, 0), (1, 0), 0.5, colors.grey),  # Linha abaixo de "Assinatura do Responsável Técnico"
        ('LINEBELOW', (0, 1), (1, 1), 0.5, colors.grey),  # Linha abaixo de "Assinatura do Recebimento Cliente" ocupando as duas colunas
        ('LINEAFTER', (0, 0), (0, 0), 0.5, colors.grey),  # Linha vertical entre "Local e Data" e "Assinatura do Responsável Técnico"
        ('BOX', (0, 0), (-1, -1), 0.5, colors.grey),  # Mantém a borda externa em volta de toda a tabela
        ('BOTTOMPADDING', (0, 0), (-1, -1), 30)  # Espaçamento inferior nas células
    ]))

    # Adiciona a tabela de assinaturas ao documento
    elements.append(signature_table)

    doc.build(elements)
    pdf = buffer.getvalue()
    buffer.close()
    response.write(pdf)
    return response

from django.shortcuts import render, get_object_or_404
from django.db.models import Sum
from .models import Protocolo, ProtocoloSemeadura

def relatorio_protocolos(request):
    # Obter todos os protocolos (filtre conforme necessário)
    user_info = get_user_info(request.user.id)
    protocolos = Protocolo.objects.all()

    protocolo_id = request.GET.get('protocolo_id')
    dados_relatorio = None
    protocolo_selecionado = None

    if protocolo_id:
        # Tenta obter o protocolo selecionado
        protocolo_selecionado = get_object_or_404(Protocolo, id=protocolo_id)

        # Obter as semeaduras associadas ao protocolo
        semeaduras = ProtocoloSemeadura.objects.filter(protocolo=protocolo_selecionado)

        # Calcular totais
        total_mudas = semeaduras.aggregate(total=Sum('qtd_especie'))['total'] or 0
        total_valor = semeaduras.aggregate(total=Sum('valor_total'))['total'] or 0

        # Preparar dados para o relatório
        dados_relatorio = {
            'data_criacao': protocolo_selecionado.data_criacao,
            'cliente_nome': protocolo_selecionado.cliente_fisico.nome_completo if protocolo_selecionado.tipo_cliente == 'F' else protocolo_selecionado.cliente_empresa.nome_fantasia,
            'total_mudas': total_mudas,
            'total_valor': total_valor,
            'semeaduras': semeaduras,
        }

    context = {
        'protocolos': protocolos,
        'protocolo_selecionado': protocolo_selecionado,
        'dados_relatorio': dados_relatorio,
        'user_info': user_info,
    }

    return render(request, 'protocolos/relatorio_protocolos.html', context)

# views.py
def relatorio_protocolo_detalhado(request, protocolo_id):
    protocolo = get_object_or_404(Protocolo, id=protocolo_id)
    semeaduras = ProtocoloSemeadura.objects.filter(protocolo=protocolo)

    total_mudas = semeaduras.aggregate(total=Sum('qtd_especie'))['total'] or 0
    total_valor = semeaduras.aggregate(total=Sum('valor_total'))['total'] or 0

    context = {
        'protocolo': protocolo,
        'semeaduras': semeaduras,
        'total_mudas': total_mudas,
        'total_valor': total_valor,
    }
    return render(request, 'protocolos/relatorio_protocolo_detalhado.html', context)
