from django.shortcuts import render, get_object_or_404
from projeto.models import Projeto
from ctermica.models import Ambiente
from termicos.models import DadosTermicos
from paredes.models import Parede 
from vidros.models import Vidro
from portas.models import Porta
from telhados.models import Telhado
from django.db import connection
from .models import CalculoTermica
from .cargasparedes import calcular_carga_termica_parede, calcular_carga_insolacao_parede
from .cargasvidros import calcular_cargas_vidros
from .cargasportas import calcular_carga_insolacao_porta, calcular_carga_termica_porta, calcular_cargas_portas
from .cargastelhados import calcular_cargas_telhados, calcular_carga_insolacao_telhado, calcular_carga_termica_telhado
from .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
)
from .cargasparedes import carregar_temperaturas_projeto2  # Carrega temperaturas e umidade do CSV

import pandas as pd
from .cargastermicos import calcular_densidade_ar
import numpy as np
import plotly.graph_objs as go
import plotly.io as pio
from django.utils.safestring import mark_safe
import os
import csv
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib import messages

@login_required
def resultados_ambiente_termica(request, projeto_id, ambiente_id):
            # Verifica se o usuário está autenticado e possui um tenant
    if request.user.is_authenticated and request.user.tenant:
        # Define o schema do tenant atual para a consulta
        connection.set_schema(request.user.tenant.schema_name)
    projeto = get_object_or_404(Projeto, id=projeto_id)
    ambiente = get_object_or_404(Ambiente, id=ambiente_id, projeto=projeto)

    # Se for um ambiente com equipamento existente, não há cálculo térmico
    if ambiente.equipamento_existente:
        messages.warning(request, "Este ambiente foi cadastrado com um equipamento existente. O cálculo térmico não foi realizado.")
        return render(request, 'calculotermica/resultados_cargatermica.html', {
            'projeto': projeto,
            'ambiente': ambiente,
            'erro': True,
            'mensagem': "Este ambiente foi preenchido automaticamente com um modelo existente e não passou pelo cálculo térmico."
        })

    termicos = get_object_or_404(DadosTermicos, ambiente=ambiente)
    paredes = Parede.objects.filter(ambiente=ambiente)
    vidros = Vidro.objects.filter(ambiente=ambiente)
    porta = Porta.objects.filter(ambiente=ambiente)
    telhados = Telhado.objects.filter(ambiente=ambiente)
#
#
#
    try:
        # Carrega dados climáticos
        temperaturas_externas, umidade_absoluta_externa, calor_latente_agua = carregar_temperaturas_projeto2(projeto_id)
    except FileNotFoundError as e:
        # Adiciona uma mensagem de erro para o usuário
        messages.error(request, str(e))
        return render(request, 'calculotermica/resultados_cargatermica.html', {
            'projeto': projeto,
            'ambiente': ambiente,
            'erro': True
        })
 
 #
 #
 #

    # Carregar dados de temperaturas, umidade e calor latente do CSV
    temperaturas_externas, umidade_absoluta_externa, calor_latente_agua = carregar_temperaturas_projeto2(projeto_id)
    temperatura_interna = termicos.temperatura_interna
#
#
#
    # Cálculo da densidade do ar com base na altitude do projeto
    altitude = projeto.altitude if projeto.altitude is not None else 0
    densidade_ar = calcular_densidade_ar(altitude)
#
#
#
    # 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, temperatura_interna, vazao_total_ar_exterior
    )
#
#
#
    calor_latente_ar_exterior = calcular_calor_latente_ar_exterior(
        densidade_ar,
        vazao_total_ar_exterior,
        umidade_absoluta_externa,
        termicos.umidade_absoluta_interna,
        hlv=calor_latente_agua
    )
#
#
#
    # Inicializar dicionários para armazenar as cargas térmicas e de insolação
    cargas_termo = {}
    cargas_insolacao = {}
    cargas_termo_vidros, cargas_insolacao_vidros = calcular_cargas_vidros(projeto_id, vidros, termicos)
    cargas_termo_portas= {}
    cargas_insolacao_portas= {}
    cargas_termo_telhados, cargas_insolacao_telhados = calcular_cargas_telhados(projeto_id, telhados, termicos)

    orientacoes = ['norte', 'sul', 'leste', 'oeste']
    horarios = ["06:00", "07:00", "08:00", "09:00", "10:00", "11:00", "12:00", "13:00", "14:00", "15:00", "16:00", "17:00", "18:00"]
#
#
#
    # Inicializar totalizadores de carga térmica e insolação para as paredes
    total_carga_termica_paredes = np.zeros(len(horarios))
    total_carga_insolacao_paredes = np.zeros(len(horarios))

    # Cálculo para paredes
    for parede in paredes:
        for orientacao in orientacoes:
            # Calcular carga térmica e de insolação para cada orientação e armazenar em cargas_termo e cargas_insolacao
            carga_termica = calcular_carga_termica_parede(projeto_id, parede, termicos, orientacao)
            carga_insolacao = calcular_carga_insolacao_parede(parede, orientacao)

            # Adicionar as cargas calculadas ao totalizador
            total_carga_termica_paredes += np.array(carga_termica)
            total_carga_insolacao_paredes += np.array(carga_insolacao)

            # Armazenar as cargas individuais para exibição detalhada por orientação
            cargas_termo[f'{orientacao}'] = carga_termica
            cargas_insolacao[f'{orientacao}'] = carga_insolacao

    # Somar as cargas térmicas e de insolação para obter o total de cálculo para paredes
    total_parede_calculo = total_carga_termica_paredes + total_carga_insolacao_paredes

    # Preparar dicionário com os totais de paredes
    cargas_totais_paredes = {
        'total_carga_termica': total_carga_termica_paredes,
        'total_carga_insolacao': total_carga_insolacao_paredes,
        'total_parede_calculo': total_parede_calculo
    }
#
#
#
    # Inicializar totalizadores de carga térmica e insolação para os vidros
    total_carga_termica_vidros = np.zeros(len(horarios))
    total_carga_insolacao_vidros = np.zeros(len(horarios))

    # Cálculo para vidros
    for orientacao, carga_termica in cargas_termo_vidros.items():
        total_carga_termica_vidros += np.array(carga_termica)
    for orientacao, carga_insolacao in cargas_insolacao_vidros.items():
        total_carga_insolacao_vidros += np.array(carga_insolacao)

    # Total de cargas para vidros
    total_vidro_calculo = total_carga_termica_vidros + total_carga_insolacao_vidros
    cargas_totais_vidros = {
        'total_carga_termica': total_carga_termica_vidros,
        'total_carga_insolacao': total_carga_insolacao_vidros,
        'total_vidro_calculo': total_vidro_calculo
    }
#
#
#
    # Totalizadores para portas (unificadas)
    total_carga_termica_portas = np.zeros(len(horarios))
    total_carga_insolacao_portas = np.zeros(len(horarios))

    # Dicionários para armazenar valores por orientação
    cargas_termo_portas = {}
    cargas_insolacao_portas = {}

    # Calcular cargas por porta e orientação
    for porta in porta:
        for orientacao in orientacoes:
            # Calcular carga térmica e de insolação
            carga_termica_porta = calcular_carga_termica_porta(projeto_id, porta, termicos, orientacao)
            carga_insolacao_porta = calcular_carga_insolacao_porta(porta, orientacao)

            # Armazenar por orientação
            cargas_termo_portas[f'{orientacao}'] = carga_termica_porta
            cargas_insolacao_portas[f'{orientacao}'] = carga_insolacao_porta

            # Acumular total
            total_carga_termica_portas += np.array(carga_termica_porta)
            total_carga_insolacao_portas += np.array(carga_insolacao_porta)

    # Cálculo final total
    total_portas_calculo = total_carga_termica_portas + total_carga_insolacao_portas

    # Dicionário com os totais consolidados
    cargas_totais_portas = {
        'total_carga_termica': total_carga_termica_portas,
        'total_carga_insolacao': total_carga_insolacao_portas,
        'total_portas_calculo': total_portas_calculo
    }


#
#
#
    # Totalizadores para telhados
    total_carga_termica_telhados = np.zeros(len(horarios))
    total_carga_insolacao_telhados = np.zeros(len(horarios))

    # Dicionários para armazenar as cargas térmicas e de insolação por telhado para exibição detalhada
    cargas_termo_telhados = {}
    cargas_insolacao_telhados = {}

    # Calcular cargas térmicas e de insolação para cada telhado
    for telhado in telhados:
        # Calcular carga térmica e de insolação para o telhado
        carga_termica_telhado = calcular_carga_termica_telhado(projeto_id, telhado, termicos)
        carga_insolacao_telhado = calcular_carga_insolacao_telhado(projeto_id, telhado, termicos)

        # Armazenar a carga do telhado para exibição detalhada com o ID do telhado como chave
        cargas_termo_telhados[f'telhado_{telhado.id}'] = carga_termica_telhado
        cargas_insolacao_telhados[f'telhado_{telhado.id}'] = carga_insolacao_telhado

        # Adicionar ao totalizador para obter o somatório total para todos os horários
        total_carga_termica_telhados += np.array(carga_termica_telhado)
        total_carga_insolacao_telhados += np.array(carga_insolacao_telhado)

    # Somar as cargas térmicas e de insolação para obter o total de cálculo para telhados
    total_telhado_calculo = total_carga_termica_telhados + total_carga_insolacao_telhados

    # Preparar dicionário com os totais de telhados
    cargas_totais_telhados = {
        'total_carga_termica': total_carga_termica_telhados,
        'total_carga_insolacao': total_carga_insolacao_telhados,
        'total_telhado_calculo': total_telhado_calculo
    }


#
#
#
    # Cálculos térmicos gerais do ambiente
    cargas_ambiente = calcular_cargas_termicas_ambiente(termicos)

    # Inicializar totalizadores para diferentes tipos de carga no ambiente
    carga_sensivel_total = np.zeros(len(horarios))
    carga_latente_total = np.zeros(len(horarios))
    carga_iluminacao = np.zeros(len(horarios))
    carga_equipamentos = np.zeros(len(horarios))
    carga_sensivel_pessoas = np.zeros(len(horarios))
    carga_latente_pessoas = np.zeros(len(horarios))

    # Somar as cargas específicas
    if 'carga_sensivel_total' in cargas_ambiente:
        carga_sensivel_total += np.array(cargas_ambiente['carga_sensivel_total'])

    if 'carga_latente_total' in cargas_ambiente:
        carga_latente_total += np.array(cargas_ambiente['carga_latente_total'])

    if 'carga_iluminacao' in cargas_ambiente:
        carga_iluminacao += np.array(cargas_ambiente['carga_iluminacao'])

    if 'carga_equipamentos' in cargas_ambiente:
        carga_equipamentos += np.array(cargas_ambiente['carga_equipamentos'])

    if 'carga_sensivel_pessoas' in cargas_ambiente:
        carga_sensivel_pessoas += np.array(cargas_ambiente['carga_sensivel_pessoas'])

    if 'carga_latente_pessoas' in cargas_ambiente:
        carga_latente_pessoas += np.array(cargas_ambiente['carga_latente_pessoas'])

    # Dicionário com totais de cargas do ambiente
    cargas_totais_ambiente = {
        'carga_sensivel_total': carga_sensivel_total,
        'carga_latente_total': carga_latente_total,
        'carga_iluminacao': carga_iluminacao,
        'carga_equipamentos': carga_equipamentos,
        "carga_sensivel_pessoas": carga_sensivel_pessoas,
        "carga_latente_pessoas": carga_latente_pessoas,
    }

#
#
#
    # Somatórios das cargas térmicas sensíveis e latentes
    somatorio_carga_sensivel_total = (
        total_parede_calculo + 
        total_vidro_calculo + 
        total_portas_calculo +
        total_telhado_calculo + 
        #carga_sensivel_total + 
        calor_sensivel_ar_exterior +
        carga_iluminacao +
        carga_equipamentos +
        carga_sensivel_pessoas

    )







    somatorio_carga_latente_total = (
        carga_latente_total + 
        calor_latente_ar_exterior
    )

    carga_termica_total_ambiente = (somatorio_carga_latente_total + somatorio_carga_sensivel_total)
    # Obter o valor máximo do array de carga térmica total do ambiente
    carga_termica_total_ambiente_max = max(carga_termica_total_ambiente)

#
#


    # Criar o caminho para o diretório do arquivo Excel
    caminho_base = os.path.join(settings.BASE_DIR, f"/var/www/html/cagpublico/cag/arquivos_cargas_termicas/projeto_{projeto.nome_projeto}")
    os.makedirs(caminho_base, exist_ok=True)
    caminho_arquivo = os.path.join(caminho_base, f"{ambiente.nome_ambiente}_resultados_termicos.xlsx")

    # Criar o DataFrame com os dados
    dados = {
        'Horário': horarios,
        'Carga Térmica Total Ambiente': carga_termica_total_ambiente,
        'Somatório Carga Latente Total': somatorio_carga_latente_total,
        'Somatório Carga Sensível Total': somatorio_carga_sensivel_total,
    }

    df = pd.DataFrame(dados)

    # Salvar o DataFrame no arquivo Excel (.xlsx)
    df.to_excel(caminho_arquivo, index=False, engine='openpyxl')



#
# Criando o gráfico da carga térmica total do ambiente ao longo do dia
# Converte a carga térmica total de W para TR
    carga_termica_total_ambiente_tr = carga_termica_total_ambiente / 3517  # Conversão de W para TR

# Criando o gráfico com ambas as unidades (W e TR)
    horarios = ["06:00", "07:00", "08:00", "09:00", "10:00", "11:00", "12:00", "13:00", "14:00", "15:00", "16:00", "17:00", "18:00"]
    fig = go.Figure()

    # Adiciona a carga térmica em Watts (W) ao gráfico
    fig.add_trace(go.Scatter(
        x=horarios,
        y=carga_termica_total_ambiente,
        mode='lines+markers',
        name='Carga Térmica Total (W)',
        yaxis="y1"  # Define o eixo y1 para a unidade em W
    ))

    # Adiciona a carga térmica em Toneladas de Refrigeração (TR) ao gráfico
    fig.add_trace(go.Scatter(
        x=horarios,
        y=carga_termica_total_ambiente_tr,
        mode='lines+markers',
        name='Carga Térmica Total (TR)',
        yaxis="y2"  # Define o eixo y2 para a unidade em TR
    ))

    # Configura o layout do gráfico com dois eixos Y
    fig.update_layout(
        title="Carga Térmica Total do Ambiente ao Longo do Dia",
        xaxis_title="Horário",
        yaxis=dict(
            title="Carga Térmica Total (W)",
            titlefont=dict(color="#1f77b4"),
            tickfont=dict(color="#1f77b4"),
            side="left"
        ),
        yaxis2=dict(
            title="Carga Térmica Total (TR)",
            titlefont=dict(color="#ff7f0e"),
            tickfont=dict(color="#ff7f0e"),
            overlaying="y",
            side="right"
        ),
        template="plotly_white"
    )

    # Converte o gráfico para HTML
    plot_carga_termica_total = pio.to_html(fig, full_html=False)
#
#
#

    # Contexto atualizado com todos os dicionários de cargas, incluindo telhados, ambiente geral, vazão de ar, altitude e densidade do ar
    contexto = {
        'projeto': projeto,
        'ambiente': ambiente,
        'cargas_totais_paredes': cargas_totais_paredes,
        'cargas_totais_vidros': cargas_totais_vidros,
        'cargas_totais_portas': cargas_totais_portas,
        'cargas_totais_telhados': cargas_totais_telhados,
        'cargas_totais_ambiente': cargas_totais_ambiente,
        'cargas_termo': cargas_termo,
        'cargas_insolacao': cargas_insolacao,
        '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,
        '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,
        'horarios': horarios,
        'altitude': altitude,
        'densidade_ar': densidade_ar,
        'somatorio_carga_sensivel_total': somatorio_carga_sensivel_total,
        'somatorio_carga_latente_total': somatorio_carga_latente_total,
        'carga_termica_total_ambiente': carga_termica_total_ambiente,
        'carga_termica_total_ambiente_max': carga_termica_total_ambiente_max,
        'plot_carga_termica_total': mark_safe(plot_carga_termica_total),

        
    }

    return render(request, 'calculotermica/resultados_cargatermica.html', contexto)

#
#
#

from .relatorio_ambiente_completo import gerar_relatorio_completo


@login_required
def relatorio_completo_view(request, projeto_id, ambiente_id):
            # Verifica se o usuário está autenticado e possui um tenant
    if request.user.is_authenticated and request.user.tenant:
        # Define o schema do tenant atual para a consulta
        connection.set_schema(request.user.tenant.schema_name)
    projeto = get_object_or_404(Projeto, id=projeto_id)
    ambiente = get_object_or_404(Ambiente, id=ambiente_id, projeto=projeto)

    # Chama a função que gera o relatório
    response = gerar_relatorio_completo(request, projeto_id, ambiente_id)
    
    return response
    






from .relatorio_ambiente_resumido import gerar_relatorio_resumido

@login_required
def relatorio_resumido_view(request, projeto_id, ambiente_id):
            # Verifica se o usuário está autenticado e possui um tenant
    if request.user.is_authenticated and request.user.tenant:
        # Define o schema do tenant atual para a consulta
        connection.set_schema(request.user.tenant.schema_name)
    projeto = get_object_or_404(Projeto, id=projeto_id)
    ambiente = get_object_or_404(Ambiente, id=ambiente_id, projeto=projeto)

    # Chama a função que gera o relatório
    response = gerar_relatorio_resumido(request, projeto_id, ambiente_id)
    
    return response

 


from calculotermica.relatorio_termo_referencia import gerar_termo_de_referencia


from django.shortcuts import get_object_or_404
from projeto.models import Projeto
from django.db import connection
from django.contrib.auth.decorators import login_required
from .relatorio_termo_referencia import gerar_termo_de_referencia

@login_required
def gerar_termo_referencia_view(request, projeto_id):
    if request.user.is_authenticated and request.user.tenant:
        connection.set_schema(request.user.tenant.schema_name)

    projeto = get_object_or_404(Projeto, id=projeto_id)
    return gerar_termo_de_referencia(request, projeto)


