from django.shortcuts import render, get_object_or_404, HttpResponse
import ezdxf
import networkx as nx
import os
from projeto.models import Projeto
from ctermica.models import Ambiente
from termicos.models import DadosTermicos
from calculotermica.cargasparedes import (
    calcular_carga_termica_parede,
    calcular_carga_insolacao_parede,
)
from calculotermica.cargasvidros import calcular_cargas_vidros
from calculotermica.cargasportas import (calcular_cargas_portas, calcular_carga_insolacao_porta, calcular_carga_termica_porta)
from calculotermica.cargastelhados import calcular_cargas_telhados
from calculotermica.cargastermicos import (
    calcular_cargas_termicas_ambiente,
    calcular_calor_sensivel_ar_exterior,
    calcular_calor_latente_ar_exterior,
    calcular_vazao_ar_infiltracao,
    calcular_vazao_ar_renovacao,
    calcular_vazao_total_ar_exterior
)

def index(request):
    # Carrega todos os projetos e os ambientes associados
    projetos = Projeto.objects.all()
    ambientes = Ambiente.objects.all()
    return render(request, 'fluxograma/fluxograma.html', {'projetos': projetos, 'ambientes': ambientes})

def exportar_fluxograma_dxf(projeto, ambiente, contexto):
    # Cria o documento DXF e o espaço de desenho
    doc = ezdxf.new(dxfversion='R2010')
    msp = doc.modelspace()

    # Definindo o layout do grafo para o fluxograma
    G = nx.DiGraph()
    G.add_node("Projeto", pos=(0, 5))
    G.add_node("Ambiente", pos=(5, 5), info=f"Temp. Interna: {contexto['ambiente'].temperatura_interna}°C")
    G.add_edge("Projeto", "Ambiente")

    # Adicionar cálculos térmicos dos elementos
    for key, value in contexto.get('cargas_termo', {}).items():
        G.add_node(f"Carga Térmica {key}", pos=(7, 4 - list(contexto['cargas_termo']).index(key)), info=f"{value} W")
        G.add_edge("Ambiente", f"Carga Térmica {key}")

    # Definir posições dos nós e plotar no DXF
    pos = nx.get_node_attributes(G, 'pos')
    for node, (x, y) in pos.items():
        info = G.nodes[node].get("info", "")
        msp.add_circle((x, y), radius=0.5, dxfattribs={'color': 3})
        msp.add_text(node, dxfattribs={'height': 0.3}).set_placement((x + 0.6, y))
        if info:
            msp.add_text(info, dxfattribs={'height': 0.2}).set_placement((x + 0.6, y - 0.4))

    for start_node, end_node in G.edges():
        start_pos = pos[start_node]
        end_pos = pos[end_node]
        msp.add_line(start_pos, end_pos, dxfattribs={'color': 7})

    # Verifica a existência do diretório antes de salvar o arquivo DXF
    dxf_path = 'fluxograma/static/fluxograma/fluxograma.dxf'
    os.makedirs(os.path.dirname(dxf_path), exist_ok=True)
    doc.saveas(dxf_path)
    return dxf_path

def gerar_fluxograma(request, projeto_id, ambiente_id):
    # Carregar dados do projeto e ambiente
    projeto = get_object_or_404(Projeto, id=projeto_id)
    ambiente = get_object_or_404(Ambiente, id=ambiente_id, projeto=projeto)
    termicos = get_object_or_404(DadosTermicos, ambiente=ambiente)

    # Valores fictícios para variáveis que precisam ser carregadas ou calculadas
    temperaturas_externas = None  # Substitua por dados reais se aplicável
    umidade_absoluta_externa = None
    calor_latente_agua = None

    # Cálculo das vazões de ar exterior
    vazao_infiltracao = calcular_vazao_ar_infiltracao(termicos.area_piso, termicos.pe_direito)
    vazao_renovacao = calcular_vazao_ar_renovacao(termicos.numero_pessoas, termicos.taxa_renovacao)
    vazao_total_ar_exterior = calcular_vazao_total_ar_exterior(
        termicos.area_piso, termicos.pe_direito, termicos.numero_pessoas, termicos.taxa_renovacao
    )

    # Cálculos de calor sensível e calor latente devido ao ar exterior
    calor_sensivel_ar_exterior = calcular_calor_sensivel_ar_exterior(
        termicos, temperaturas_externas, termicos.temperatura_interna, vazao_total_ar_exterior
    )
    calor_latente_ar_exterior = calcular_calor_latente_ar_exterior(
        termicos, umidade_absoluta_externa, termicos.umidade_absoluta_interna, calor_latente_agua, vazao_total_ar_exterior
    )

    # Cálculo de cargas térmicas para paredes, vidros, portas e telhados
    paredes = ambiente.parede_set.all()
    cargas_termo_paredes = {
        parede.orientacao: calcular_carga_termica_parede(projeto_id, parede, termicos, parede.orientacao)
        for parede in paredes
    }
    cargas_insolacao_paredes = {
        parede.orientacao: calcular_carga_insolacao_parede(parede, parede.orientacao)
        for parede in paredes
    }

    vidros = ambiente.vidro_set.all()
    cargas_termo_vidros, cargas_insolacao_vidros = calcular_cargas_vidros(projeto_id, vidros, termicos)

    # Cálculos para portas (modelo unificado)
    portas = ambiente.porta_set.all()
    cargas_termo_portas = {
        porta.orientacao: calcular_carga_termica_porta(projeto_id, porta, termicos, porta.orientacao)
        for porta in portas
    }
    cargas_insolacao_portas = {
        porta.orientacao: calcular_carga_insolacao_porta(porta, porta.orientacao)
        for porta in portas
    }


    telhados = ambiente.telhado_set.all()
    cargas_termo_telhados, cargas_insolacao_telhados = calcular_cargas_telhados(projeto_id, telhados, termicos)

    # Cálculos térmicos gerais do ambiente
    cargas_ambiente = calcular_cargas_termicas_ambiente(termicos)

    # Criação do contexto com todas as variáveis calculadas
    contexto = {
        'projeto': projeto,
        'ambiente': ambiente,
        'vazao_infiltracao': vazao_infiltracao,
        'vazao_renovacao': vazao_renovacao,
        'vazao_total_ar_exterior': vazao_total_ar_exterior,
        'calor_sensivel_ar_exterior': calor_sensivel_ar_exterior,
        'calor_latente_ar_exterior': calor_latente_ar_exterior,
        'cargas_termo_paredes': cargas_termo_paredes,
        'cargas_insolacao_paredes': cargas_insolacao_paredes,
        'cargas_termo_vidros': cargas_termo_vidros,
        'cargas_insolacao_vidros': cargas_insolacao_vidros,
        'cargas_termo_portas': cargas_termo_portas,
        'cargas_insolacao_portas': cargas_insolacao_portas,
        'cargas_termo_telhados': cargas_termo_telhados,
        'cargas_insolacao_telhados': cargas_insolacao_telhados,
        'cargas_ambiente': cargas_ambiente,
    }

    # Exportar o fluxograma com resultados em DXF
    try:
        dxf_path = exportar_fluxograma_dxf(projeto, ambiente, contexto)
    except Exception as e:
        # Retorna uma resposta de erro caso ocorra algum problema ao gerar o DXF
        return HttpResponse(f"Erro ao exportar o fluxograma DXF: {e}", status=500)

    # Tentar abrir o arquivo DXF gerado e prepará-lo para download
    try:
        with open(dxf_path, 'rb') as f:
            response = HttpResponse(f.read(), content_type='application/dxf')
            response['Content-Disposition'] = 'attachment; filename="fluxograma.dxf"'
        return response
    except FileNotFoundError:
        # Responde com erro caso o arquivo não seja encontrado
        return HttpResponse("Arquivo DXF não encontrado. Verifique o caminho do diretório.", status=404)
    except Exception as e:
        # Responde com erro para qualquer outra exceção inesperada durante o download
        return HttpResponse(f"Erro ao processar o download do fluxograma DXF: {e}", status=500)

