from django.shortcuts import render, redirect, get_object_or_404
from apps.dashboard.utils import get_user_info
from apps.lotes.forms import LoteForms, SemeaduraForms
from django.contrib import messages
from apps.lotes.models import CadastroLote, Semeadura, LogExclusaoLote
from apps.especies.models import Especies
from apps.fornecedores.models import FornecedoresModels
from apps.producao.models import PorcentagemColeta, ProducaoMudas
from datetime import datetime
from datetime import date
import logging
from decimal import Decimal
from django.db import transaction
from django.conf import settings
from django.utils import timezone
from django.views.decorators.http import require_POST
from django.utils.safestring import mark_safe
from apps.repique.models import Repique
from apps.estufa.models import Estufa, Selecao

def obter_proxima_sequencia(especie_id, data_lote):
    """
    Gera a próxima sequência baseada APENAS no ano (dois últimos dígitos).
    Se no ano 25 já existe 25.L1, 25.L2..., o próximo é 25.L3 (independente do que vier antes).
    Formato final que vamos gerar: <especie_id>.<ano_lote>.L<sequencia>
    mas o filtro ignora o especie_id e só se baseia no .<ano_lote>.L
    """

    from apps.lotes.models import CadastroLote  # Ajuste se necessário

    ano_lote = data_lote.year % 100  # 2024 => 24, 2025 => 25...
    # Monta o pedacinho que será usado para filtrar qualquer lote do mesmo ano
    filtro_ano = f".{ano_lote}.L"

    lotes_do_ano = CadastroLote.objects.filter(
        numero_lote__contains=filtro_ano
    ).values_list('numero_lote', flat=True)

    maior_sequencia = 0
    if lotes_do_ano:
        sequencias = []
        for lote_str in lotes_do_ano:
            # "16.24.L1" -> split(".24.L") -> ["16", "1"]
            # "192.25.L1" -> split(".25.L") -> ["192", "1"]
            parts = lote_str.split(filtro_ano)
            if len(parts) == 2:
                seq_str = parts[1]  # ex: "1"
                try:
                    seq_int = int(seq_str)
                    sequencias.append(seq_int)
                except ValueError:
                    pass
        if sequencias:
            maior_sequencia = max(sequencias)

    proxima = maior_sequencia + 1
    # Montar do jeito que você quiser
    # Exemplo: "<especie_id>.<ano_lote>.L<seq>"
    proxima_sequencia = f"{especie_id}.{ano_lote}.L{proxima}"

    return proxima_sequencia

def cadastro_lote(request, especie_id):
    especie = get_object_or_404(Especies, id=especie_id)

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

    user_info = get_user_info(request.user.id)
    form = None
    lote = None

    try:
        porcentagem_data = PorcentagemColeta.objects.get(especie=especie)
        producao_data = ProducaoMudas.objects.get(especie=especie)

        if request.method == 'POST':
            form = LoteForms(request.POST, request.FILES)
            if form.is_valid():
                lote = form.save(commit=False)
                lote.registrado_por = request.user

                # Vamos pegar a data_lote do formulário validado
                data_lote_informada = form.cleaned_data.get('data_lote')

                # Se não houver ano preenchido, podemos usar o ano da data_lote
                if not lote.ano and data_lote_informada:
                    lote.ano = data_lote_informada.year

                # Gera o número do lote baseado na data_lote
                if not lote.numero_lote:
                    lote.numero_lote = obter_proxima_sequencia(especie_id, data_lote_informada)


                lote.numero_sementes_por_kg = producao_data.numero_sementes_por_kg

                # Arredonde os valores antes de atribuir aos campos do modelo
                lote.valor_minimo = round(
                    porcentagem_data.valor_minimo * lote.numero_sementes_por_kg, 3)
                lote.valor_maximo = round(
                    porcentagem_data.valor_maximo * lote.numero_sementes_por_kg, 3)

                lote.especie_id = especie_id

                # Obtenha o fornecedor selecionado do formulário
                fornecedor_selecionado_id = form.cleaned_data.get('fornecedor')

                # Verifique se um fornecedor foi selecionado antes de tentar acessar 'nome_fantasia'
                if fornecedor_selecionado_id:
                    try:
                        fornecedor_selecionado = FornecedoresModels.objects.get(id=fornecedor_selecionado_id)
                        lote.fornecedor = fornecedor_selecionado.nome_fantasia
                    except FornecedoresModels.DoesNotExist:
                        lote.fornecedor = None
                else:
                    lote.fornecedor = None

                lote.save()
                messages.success(request, mark_safe(
                    '<i class="fa-solid fa-circle-check"></i><strong class="mx-1">Sucesso!</strong> Lote cadastrado com êxito.'))
                return redirect('lista_especies')
            else:
                print(form.errors)
                messages.error(request, mark_safe(
                    '<i class="fa-solid fa-circle-exclamation"></i><strong class="mx-1">Erro!</strong> no formulário. Verifique os dados inseridos.'))
        else:
            form = LoteForms(initial={
                'especies': especie.especies,
                'nome_popular': especie.nome_popular,
                'valor_minimo': round(porcentagem_data.valor_minimo, 0) if porcentagem_data else 0,
                'valor_maximo': round(porcentagem_data.valor_maximo, 0) if porcentagem_data else 0,
                'numero_sementes_por_kg': producao_data.numero_sementes_por_kg if producao_data else 0,
                'qtd_sementes_minimo': round((porcentagem_data.valor_minimo * producao_data.numero_sementes_por_kg) / 100, 0) if porcentagem_data and producao_data else 0,
                'qtd_sementes_maximo': round((porcentagem_data.valor_maximo * producao_data.numero_sementes_por_kg) / 100, 0) if porcentagem_data and producao_data else 0,
            })
            lote = CadastroLote()

    except Exception as e:
        messages.error(request, f"Erro ao salvar lote: {e}")
        print(f"Erro ao salvar lote: {e}")

    return render(request, 'lotes/cadastro_lote.html', {"form": form, "lote": lote, "user_info": user_info, 'especie': especie})


def editar_lote(request, especie_id, lote_id):
    especie = get_object_or_404(Especies, id=especie_id)
    lote = get_object_or_404(CadastroLote, id=lote_id)

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

    user_info = get_user_info(request.user.id)
    form = None

    try:
        porcentagem_data = PorcentagemColeta.objects.get(especie=especie)
        producao_data = ProducaoMudas.objects.get(especie=especie)

        if request.method == 'POST':
            # 1) Guarde a data_lote antes de atualizar o lote
            data_lote_original = lote.data_lote

            # 2) Atualize com o que veio do POST
            form = LoteForms(request.POST, request.FILES, instance=lote)
            if form.is_valid():
                with transaction.atomic():
                    lote = form.save(commit=False)

                    # Pega a nova data_lote que veio do formulário
                    data_lote_informada = form.cleaned_data.get('data_lote')

                    # Se a data_lote foi alterada, ou se estiver em branco e quisermos forçar
                    if data_lote_informada and data_lote_informada != data_lote_original:
                        # Gere um novo número de lote baseado na nova data
                        lote.numero_lote = obter_proxima_sequencia(especie_id, data_lote_informada)

                    # Se o campo 'ano' estiver vazio, podemos usar o ano da data_lote (opcional)
                    if not lote.ano and data_lote_informada:
                        lote.ano = data_lote_informada.year

                    # Ajustes nos demais campos
                    lote.numero_sementes_por_kg = producao_data.numero_sementes_por_kg
                    lote.valor_minimo = porcentagem_data.valor_minimo * lote.numero_sementes_por_kg
                    lote.valor_maximo = porcentagem_data.valor_maximo * lote.numero_sementes_por_kg
                    lote.especie_id = especie_id

                    # Verifique o fornecedor
                    fornecedor_selecionado_id = form.cleaned_data.get('fornecedor')
                    if fornecedor_selecionado_id:
                        try:
                            fornecedor_selecionado = FornecedoresModels.objects.get(id=fornecedor_selecionado_id)
                            lote.fornecedor = fornecedor_selecionado.nome_fantasia
                        except FornecedoresModels.DoesNotExist:
                            lote.fornecedor = None
                    else:
                        lote.fornecedor = None

                    # Salva
                    lote.save()
                    messages.success(request, mark_safe(
                        '<i class="fa-solid fa-circle-check"></i><strong class="mx-1">Sucesso!</strong> Lote editado com êxito.'))
                    return redirect('lista_estoque')
            else:
                messages.error(request, mark_safe(
                    '<i class="fa-solid fa-circle-exclamation"></i><strong class="mx-1">Erro!</strong> no formulário. Verifique os dados inseridos.'))
        else:
            # Carrega o formulário no GET
            form = LoteForms(instance=lote, initial={
                'especies': especie.especies,
                'nome_popular': especie.nome_popular,
                'valor_minimo': porcentagem_data.valor_minimo if porcentagem_data else 0,
                'valor_maximo': porcentagem_data.valor_maximo if porcentagem_data else 0,
                'numero_sementes_por_kg': producao_data.numero_sementes_por_kg if producao_data else 0,
                'qtd_sementes_minimo': (porcentagem_data.valor_minimo * producao_data.numero_sementes_por_kg) / 100 if porcentagem_data and producao_data else 0,
                'qtd_sementes_maximo': (porcentagem_data.valor_maximo * producao_data.numero_sementes_por_kg) / 100 if porcentagem_data and producao_data else 0,
                'data_lote': lote.data_lote.strftime('%Y-%m-%d') if lote.data_lote else None,
            })

    except Exception as e:
        messages.error(request, f"Erro ao editar lote: {e}")
        logging.error(f"Erro ao editar lote: {e}", exc_info=True)

    return render(request, 'lotes/editar_lote.html', {
        "form": form,
        "lote": lote,
        "user_info": user_info,
        'especie': especie
    })

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

    user_info = get_user_info(request.user.id)

    # Obtenha o ano e o mês selecionados a partir dos parâmetros da URL
    ano_selecionado = request.GET.get('ano')
    mes_selecionado = request.GET.get('mes')

    # Obtenha os lotes filtrando pelo ano e/ou mês selecionados, se fornecidos
    lotes = CadastroLote.objects.all()
    if ano_selecionado:
        lotes = lotes.filter(data_lote__year=ano_selecionado)
    if mes_selecionado:
        lotes = lotes.filter(data_lote__month=mes_selecionado)

    # Processe os lotes conforme necessário
    base_url = settings.MEDIA_URL
    for lote in lotes:
        lote.porcentagem_coleta = get_object_or_404(
            PorcentagemColeta, especie=lote.especie)
        lote.especie.foto_especie = f"{base_url}{lote.especie.foto_especie}"

    # Obtenha os anos disponíveis para o filtro
    anos_disponiveis = CadastroLote.objects.dates(
        'data_lote', 'year').distinct()

    # Opcional: Definir uma lista de meses para o filtro
    meses = [
        {'numero': 1, 'nome': 'Janeiro'},
        {'numero': 2, 'nome': 'Fevereiro'},
        {'numero': 3, 'nome': 'Março'},
        {'numero': 4, 'nome': 'Abril'},
        {'numero': 5, 'nome': 'Maio'},
        {'numero': 6, 'nome': 'Junho'},
        {'numero': 7, 'nome': 'Julho'},
        {'numero': 8, 'nome': 'Agosto'},
        {'numero': 9, 'nome': 'Setembro'},
        {'numero': 10, 'nome': 'Outubro'},
        {'numero': 11, 'nome': 'Novembro'},
        {'numero': 12, 'nome': 'Dezembro'},
    ]

    return render(request, 'lotes/lista_lotes.html', {
        'lotes': lotes,
        'anos_disponiveis': anos_disponiveis,
        'ano_selecionado': ano_selecionado,
        'mes_selecionado': mes_selecionado,
        'meses': meses,
        "user_info": user_info
    })


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

    user_info = get_user_info(request.user.id)
    # Exclui os lotes com entrada_sementes_kg igual a 0
    lotes = CadastroLote.objects.exclude(entrada_sementes_kg=0)

    base_url = settings.MEDIA_URL

    for lote in lotes:
        lote.porcentagem_coleta = get_object_or_404(
            PorcentagemColeta, especie=lote.especie)
        lote.especie.foto_especie = f"{base_url}{lote.especie.foto_especie}"

    return render(request, 'lotes/lista_estoque.html', {'lotes': lotes, "user_info": user_info})


@require_POST
def excluir_lote(request, lote_id):
    if not request.user.is_authenticated:
        return redirect('index')

    lote = get_object_or_404(CadastroLote, id=lote_id)

    motivo_exclusao = request.POST.get('motivo_exclusao', '')
    motivo_exclusao_outros = request.POST.get('motivo_exclusao_outros', '')

    # Verifica se o motivo é "Outros" e se há texto digitado
    motivo_final = motivo_exclusao_outros if motivo_exclusao == 'Outros' and motivo_exclusao_outros else motivo_exclusao

    with transaction.atomic():
        # Salva os dados no modelo LogExclusaoLote
        log_exclusao = LogExclusaoLote.objects.create(
            lote_id=lote.id,
            numero_lote=lote.numero_lote,
            data_lote=lote.data_lote,
            fornecedor=lote.fornecedor,
            data_exclusao=timezone.now().date(),
            hora_exclusao=timezone.now().time(),
            usuario_exclusao=request.user,
            nome_usuario_exclusao=request.user.username,
            motivo_exclusao=motivo_final,
            motivo_exclusao_outros=motivo_exclusao_outros
        )

        # Deleta o lote
        lote.delete()
        messages.success(request, mark_safe(
            '<i class="fa-solid fa-circle-check"></i><strong class="mx-1">Sucesso!</strong> Lote deletado com êxito.'))
    return redirect('lista_estoque')

def semeadura_lote(request, especie_id, lote_id):
    especie = get_object_or_404(Especies, id=especie_id)
    lote = get_object_or_404(CadastroLote, id=lote_id)
    semeaduras = Semeadura.objects.filter(lote=lote)

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

    user_info = get_user_info(request.user.id)

    try:
        porcentagem_data = PorcentagemColeta.objects.get(especie=especie)
        producao_data = ProducaoMudas.objects.get(especie=especie)
    except Exception as e:
        messages.error(request, mark_safe(
            f'<i class="fa-solid fa-circle-exclamation"></i><strong class="mx-1">Erro!</strong> ao obter dados: {e}'))
        logging.error(f"Erro ao obter dados: {e}", exc_info=True)
        return redirect('lista_lotes')

    initial_data = {
        'lote': lote,
        'especies': especie.especies,
        'nome_popular': especie.nome_popular,
        'valor_minimo': porcentagem_data.valor_minimo if porcentagem_data else 0,
        'valor_maximo': porcentagem_data.valor_maximo if porcentagem_data else 0,
        'numero_sementes_por_kg': '{:.2f}'.format(float(producao_data.numero_sementes_por_kg)) if producao_data else 0,
        'qtd_sementes_minimo': (porcentagem_data.valor_minimo * producao_data.numero_sementes_por_kg) / 100 if porcentagem_data and producao_data else 0,
        'qtd_sementes_maximo': (porcentagem_data.valor_maximo * producao_data.numero_sementes_por_kg) / 100 if porcentagem_data and producao_data else 0,
        'data_lote': lote.data_lote.strftime('%Y-%m-%d'),
        'numero_muda': lote.numero_lote,
    }

    quebra_dormencia = lote.quebra_dormencia

    if request.method == 'POST':
        try:
            form = SemeaduraForms(request.POST, initial=initial_data)
            if form.is_valid():
                semeadura = form.save(commit=False)
                semeadura.registrado_por = request.user
                semeadura.lote = lote

                tipo_selecao = request.POST.get('tipo_selecao', None)
                if tipo_selecao == 'cliente':
                    semeadura.empresa = None
                elif tipo_selecao == 'empresa':
                    semeadura.cliente = None

                if Decimal(str(lote.entrada_sementes_kg)) <= 0:
                    messages.error(request, mark_safe(
                        '<i class="fa-solid fa-circle-exclamation"></i><strong class="mx-1">Erro!</strong> Acabou estas sementes. Não é possível semear mais.'))
                    return redirect('lista_estoque')

                semeadura.save()

                lote.entrada_sementes_kg -= Decimal(
                    str(semeadura.qtd_sementes_utilizada))
                lote.save()
                messages.success(request, mark_safe(
                    '<i class="fa-solid fa-circle-check"></i><strong class="mx-1">Sucesso!</strong> Semeadura registrada com êxito.'))
                return redirect('lista_estoque')
            else:
                messages.error(request, mark_safe(
                        '<i class="fa-solid fa-circle-exclamation"></i><strong class="mx-1">Erro!</strong> no formulário. Verifique os dados inseridos.'))
                print(form.errors)
        except Exception as e:
            messages.error(request, mark_safe(
                        f'<i class="fa-solid fa-circle-exclamation"></i><strong class="mx-1">Erro!</strong> ao registrar semeadura: {e}'))
            logging.error(f"Erro ao registrar semeadura: {e}", exc_info=True)
            form = SemeaduraForms(instance=lote, initial=initial_data)
    else:
        form = SemeaduraForms(instance=lote, initial=initial_data)

    return render(request, 'lotes/semeadura_lote.html', {
        "form": form,
        "lote": lote,
        "user_info": user_info,
        'especie': especie,
        'quebra_dormencia': quebra_dormencia,
        'semeaduras': semeaduras,
    })

def delete_semeadura(request, semeadura_id):
    semeadura = get_object_or_404(Semeadura, id=semeadura_id)
    if not request.user.is_authenticated:
        return redirect('index')

    # Verificar se existe algum repique associado à semeadura
    if Repique.objects.filter(semeadura=semeadura).exists():
        messages.error(request, 'Esta semeadura não pode ser excluída porque já possui um repique associado.')
        return redirect('lista_repique')

    if request.method == 'POST':
        lote = semeadura.lote  # Guardar referência ao lote antes de excluir

        # Retornar a quantidade de sementes utilizada para o lote
        lote.entrada_sementes_kg += Decimal(str(semeadura.qtd_sementes_utilizada))
        lote.save()
        
        # Excluir a semeadura
        semeadura.delete()
        messages.success(request, 'Semeadura excluída com sucesso e quantidade de sementes devolvida ao lote.')

        # Redirecionar para a URL 'lista_repique'
        return redirect('lista_repique')

    # Se a solicitação não for POST, mostrar uma mensagem de erro
    messages.error(request, 'Ação inválida.')
    return redirect('lista_repique')

def editar_semeadura_lote(request, especie_id, lote_id):
    especie = get_object_or_404(Especies, id=especie_id)
    lote = get_object_or_404(CadastroLote, id=lote_id)

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

    user_info = get_user_info(request.user.id)

    try:
        porcentagem_data = PorcentagemColeta.objects.get(especie=especie)
        producao_data = ProducaoMudas.objects.get(especie=especie)

    except Exception as e:
        messages.error(request, mark_safe(
            f'<i class="fa-solid fa-circle-exclamation"></i><strong class="mx-1">Erro!</strong> ao obter dados: {e}'))
        logging.error(f"Erro ao obter dados: {e}", exc_info=True)
        return redirect('lista_lotes')

 

    # Crie um dicionário com os dados iniciais do formulário
    initial_data = {
        'lote': lote,
        'especies': especie.especies,
        'nome_popular': especie.nome_popular,
        'valor_minimo': porcentagem_data.valor_minimo if porcentagem_data else 0,
        'valor_maximo': porcentagem_data.valor_maximo if porcentagem_data else 0,
        'numero_sementes_por_kg': '{:.2f}'.format(float(producao_data.numero_sementes_por_kg)) if producao_data else 0,
        'qtd_sementes_minimo': (porcentagem_data.valor_minimo * producao_data.numero_sementes_por_kg) / 100 if porcentagem_data and producao_data else 0,
        'qtd_sementes_maximo': (porcentagem_data.valor_maximo * producao_data.numero_sementes_por_kg) / 100 if porcentagem_data and producao_data else 0,
        'data_lote': lote.data_lote.strftime('%Y-%m-%d'),
        'numero_muda': lote.numero_lote,
        
    }

    if request.method == 'POST':
        try:
            form = SemeaduraForms(request.POST, initial=initial_data)
            if form.is_valid():
                semeadura = form.save(commit=False)
                semeadura.lote = lote

                # Nova lógica aqui
                tipo_selecao = request.POST.get('tipo_selecao', None)
                if tipo_selecao == 'cliente':
                    semeadura.empresa = None
                elif tipo_selecao == 'empresa':
                    semeadura.cliente = None

                if Decimal(str(lote.entrada_sementes_kg)) <= 0:
                    messages.error(request, mark_safe(
                        '<i class="fa-solid fa-circle-exclamation"></i><strong class="mx-1">Erro!</strong> Acabou estas sementes. Não é possível semear mais.'))
                    return redirect('lista_estoque')

                semeadura.save()

                lote.entrada_sementes_kg -= Decimal(
                    str(semeadura.qtd_sementes_utilizada))
                lote.save()
                messages.success(request, mark_safe(
                    '<i class="fa-solid fa-circle-check"></i><strong class="mx-1">Sucesso!</strong> Semeadura registrada com êxito.'))
                return redirect('lista_estoque')
            else:
                messages.error(request, mark_safe(
                        '<i class="fa-solid fa-circle-exclamation"></i><strong class="mx-1">Erro!</strong> no formulário. Verifique os dados inseridos.'))
                print(form.errors)
        except Exception as e:
            messages.error(request, mark_safe(
                        f'<i class="fa-solid fa-circle-exclamation"></i><strong class="mx-1">Erro!</strong> ao registrar semeadura: {e}'))
            logging.error(f"Erro ao registrar semeadura: {e}", exc_info=True)
            # Se algo der errado, instancie o formulário com os dados iniciais
            form = SemeaduraForms(instance=lote, initial=initial_data)
    else:
        form = SemeaduraForms(instance=lote, initial=initial_data)

    return render(request, 'lotes/editar_semeadura_lote.html', {"form": form, "lote": lote, "user_info": user_info, 'especie': especie})

from django.db.models import Q

def relatorio_lotes(request):
    user_info = get_user_info(request.user.id)
    # Busca todos os lotes
    all_lotes = CadastroLote.objects.select_related('especie').all()
    selected_lote_id = request.GET.get('lote_id', '')

    if selected_lote_id:
        # Lotes
        lotes = all_lotes.filter(id=selected_lote_id)

        # Semeaduras
        semeaduras = Semeadura.objects.filter(lote__id=selected_lote_id)

        # Repiques
        repiques = Repique.objects.filter(
            Q(cadastro_lote_id=selected_lote_id) |
            Q(semeadura__lote__id=selected_lote_id)
        )

        # Estufas
        estufas = Estufa.objects.filter(semeadura__lote__id=selected_lote_id)

        # Seleção
        selecoes = Selecao.objects.filter(semeadura__lote__id=selected_lote_id)
    else:
        # Caso nada seja selecionado, retorna vazio
        lotes = all_lotes.none()
        semeaduras = Semeadura.objects.none()
        repiques = Repique.objects.none()
        estufas = Estufa.objects.none()
        selecoes = Selecao.objects.none()

    context = {
        'all_lotes': all_lotes,
        'lotes': lotes,
        'semeaduras': semeaduras,
        'repiques': repiques,
        'estufas': estufas,
        'selecoes': selecoes,
        'selected_lote_id': selected_lote_id,
        'user_info': user_info,
    }
    return render(request, 'lotes/relatorio_lotes.html', context)