import os
import pandas as pd
from django.shortcuts import render
from django.conf import settings
from projeto.models import Projeto
from ctermica.models import Ambiente
from itertools import combinations_with_replacement
from .fancoletes import FANCOLETES_MODELOS
from django.db import connection 
from django.contrib.auth.decorators import login_required

# Função para determinar a melhor combinação de fancoletes para atender à carga térmica máxima

def determinar_fancoletes(carga_maxima_watts):
    aparelhos = sorted(FANCOLETES_MODELOS, key=lambda x: x['calor_total_resfriamento_btu_h'] * 0.293071)
    melhor_comb = None
    menor_excesso = float('inf')

    for r in range(1, 11):
        for comb in combinations_with_replacement(aparelhos, r):
            capacidade_total = sum(aparelho['calor_total_resfriamento_btu_h'] * 0.293071 for aparelho in comb)
            excesso = capacidade_total - carga_maxima_watts
            if capacidade_total >= carga_maxima_watts and excesso < menor_excesso:
                melhor_comb = comb
                menor_excesso = excesso

    return list(melhor_comb) if melhor_comb else "Não há combinação adequada de fancoletes."



# Lista os projetos e ambientes para o sistema de água gelada
@login_required
def lista_projetos_agua(request):
             
    if request.user.is_authenticated and request.user.tenant:        
        connection.set_schema(request.user.tenant.schema_name)
    projetos = Projeto.objects.all()
    lista_projetos = []

    for projeto in projetos:
        ambientes = Ambiente.objects.filter(projeto=projeto)
        resumo_ambientes = []

        for ambiente in ambientes:
            try:
                caminho_base = os.path.join(settings.BASE_DIR, f"/var/www/html/cagpublico/cag/arquivos_cargas_termicas/projeto_{projeto.nome_projeto}")
                caminho_arquivo = os.path.join(caminho_base, f"{ambiente.nome_ambiente}_resultados_termicos.xlsx")
                if not os.path.exists(caminho_arquivo):
                    carga_termica_max = "Arquivo não encontrado"
                    aparelho_detalhes = "Não disponível"
                else:
                    df = pd.read_excel(caminho_arquivo, engine='openpyxl')
                    if 'Carga Térmica Total Ambiente' in df.columns:
                        carga_termica_max = df['Carga Térmica Total Ambiente'].max()
                        aparelho_detalhes = determinar_fancoletes(carga_termica_max)
                    else:
                        carga_termica_max = "Coluna não encontrada"
                        aparelho_detalhes = "Não disponível"
            except Exception as e:
                carga_termica_max = f"Erro ao processar arquivo: {e}"
                aparelho_detalhes = "Não disponível"

            resumo_ambientes.append({
                'nome': ambiente.nome_ambiente,
                'carga_termica_max': carga_termica_max,
                'aparelho_detalhes': aparelho_detalhes,
            })

        lista_projetos.append({
            'projeto_nome': projeto.nome_projeto,
            'projeto_id': projeto.id,
            'ambientes': resumo_ambientes,
        })

    contexto = {
        'lista_projetos': lista_projetos,
    }
    return render(request, 'calculocag/calculo_cag.html', contexto)



# Função para calcular o somatório dos valores dos fancoletes selecionados
@login_required
def detalhes_fancoletes(request, projeto_id, ambiente_id):
    if request.user.is_authenticated and request.user.tenant:        
        connection.set_schema(request.user.tenant.schema_name)   
    projeto = Projeto.objects.get(id=projeto_id)
    ambiente = Ambiente.objects.get(id=ambiente_id)

    # Busca a carga térmica máxima do ambiente a partir do arquivo
    try:
        caminho_base = os.path.join(settings.BASE_DIR, f"/var/www/html/cagpublico/cag/arquivos_cargas_termicas/projeto_{projeto.nome_projeto}")
        caminho_arquivo = os.path.join(caminho_base, f"{ambiente.nome_ambiente}_resultados_termicos.xlsx")
        if not os.path.exists(caminho_arquivo):
            carga_termica_max = None
            fancoletes_selecionados = "Arquivo não encontrado"
        else:
            df = pd.read_excel(caminho_arquivo, engine='openpyxl')
            if 'Carga Térmica Total Ambiente' in df.columns:
                carga_termica_max = df['Carga Térmica Total Ambiente'].max()
                fancoletes_selecionados = determinar_fancoletes(carga_termica_max)
            else:
                carga_termica_max = None
                fancoletes_selecionados = "Coluna não encontrada"
    except Exception as e:
        carga_termica_max = None
        fancoletes_selecionados = f"Erro ao processar arquivo: {e}"

    # Inicializa variáveis para somar os valores desejados
    total_vazao_agua_m3_h = 0
    total_calor_total_resfriamento_btu_h = 0
    total_calor_sensivel_btu_h = 0

    # Calcula os somatórios apenas se fancoletes selecionados são uma lista de aparelhos
    if isinstance(fancoletes_selecionados, list):
        for fancoletes in fancoletes_selecionados:
            total_vazao_agua_m3_h += fancoletes['vazao_agua_m3_h']
            total_calor_total_resfriamento_btu_h += fancoletes['calor_total_resfriamento_btu_h']
            total_calor_sensivel_btu_h += fancoletes['calor_sensivel_btu_h']

    contexto = {
        'projeto': projeto,
        'ambiente': ambiente,
        'fancoletes_selecionados': fancoletes_selecionados,
        'total_vazao_agua_m3_h': total_vazao_agua_m3_h,
        'total_calor_total_resfriamento_btu_h': total_calor_total_resfriamento_btu_h,
        'total_calor_sensivel_btu_h': total_calor_sensivel_btu_h,
    }

    return render(request, 'calculocag/detalhes_fancoletes.html', contexto)

from django.shortcuts import render, get_object_or_404
from projeto.models import Projeto
import numpy as np
import matplotlib.pyplot as plt
from io import BytesIO
import base64
from colebrook import sjFriction

from django.shortcuts import render, get_object_or_404
from projeto.models import Projeto
import numpy as np
import matplotlib.pyplot as plt
from io import BytesIO
import base64
from colebrook import sjFriction
from django.contrib import messages


from django.contrib.auth.decorators import login_required
from django.shortcuts import render, get_object_or_404
from django.contrib import messages
from django.db import connection
from io import BytesIO
import base64
import numpy as np
import matplotlib.pyplot as plt

# Certifique-se de definir ou importar a função sjFriction
# from seu_modulo import sjFriction

@login_required
def calcular_cag(request, projeto_id):
    if request.user.tenant:
        connection.set_schema(request.user.tenant.schema_name)
    
    projeto = get_object_or_404(Projeto, id=projeto_id)

    # Variáveis padrão
    μ = 0.00089  # Viscosidade dinâmica do fluido (Pa.s)
    ρ = 997.05  # Massa específica do fluido (kg/m³)
    custo_aco_default = 18  # Custo do aço (R$/kg)
    custo_energia_default = 1.15  # Custo da energia (R$/kWh)
    rendimento_bomba_default = 0.65  # Rendimento da bomba (decimal)
    horas_uso_default = 3600  # Horas de operação por ano
    nv = 10  # Número de variações de velocidade

    # Inicialização de variáveis de saída
    vazao_max, resultados, custos_totais, velocidades = None, [], [], []
    di_min, custo_total, custos, curva_bomba_base64, perda_carga_base64, custo_total_base64 = None, None, {}, None, None, None

    if request.method == "POST":
        try:
            # Captura dos dados do formulário
            Lp = float(request.POST.get("Lp", 26))  # Comprimento Primário (m)
            Ls = float(request.POST.get("Ls", 48))  # Comprimento Secundário (m)
            carga_termica = float(request.POST.get("carga_termica", 0))  # Carga Térmica (TR)
            custo_valvulas = float(request.POST.get("custo_valvulas", 0))  # Custo das válvulas (R$)
            custo_acessorios = float(request.POST.get("custo_acessorios", 0))  # Custo dos acessórios (R$)
            custo_bomba_unitaria = float(request.POST.get("custo_bomba_unitaria", 0))  # Custo unitário da bomba (R$)
            custo_chiller_unit = float(request.POST.get("custo_chiller_unit", 0))  # Custo unitário do chiller (R$/TR)
            custo_tubulacao_unitaria = float(request.POST.get("custo_tubulacao_unitaria", 0))  # Custo da tubulação (R$/m³)
            cop_chiller = float(request.POST.get("cop_chiller", 3.5))  # COP do chiller
            rendimento_bomba = float(request.POST.get("rendimento_bomba", rendimento_bomba_default)) / 100
            custo_energia = float(request.POST.get("custo_energia", custo_energia_default))
            custo_aco = float(request.POST.get("custo_aco", custo_aco_default))
            horas_uso = float(request.POST.get("horas_uso", horas_uso_default))

            # Validações
            if carga_termica <= 0:
                raise ValueError("A carga térmica deve ser maior que zero.")
            if rendimento_bomba <= 0 or rendimento_bomba > 1:
                raise ValueError("O rendimento da bomba deve estar entre 0 e 100%.")
            if cop_chiller <= 0:
                raise ValueError("O COP do chiller deve ser maior que zero.")

        except ValueError as e:
            messages.error(request, f"Erro nos dados de entrada: {e}")
            return render(request, 'calculocag/resultados_cag.html', {'projeto_id': projeto_id})

        # Cálculo da vazão máxima
        vazao_max = round(((carga_termica * 3.51) / (4180 * 5.5)) * 3600, 2)  # m³/h
        Lt = Lp + Ls  # Comprimento total

        # Cálculos de variações de velocidade
        vi = np.linspace(1.0, 4.5, nv)
        for v in vi:
            try:
                # Cálculo do diâmetro interno (mm)
                di = np.sqrt((4 * vazao_max / 3600) / (v * np.pi)) * 1000
                e = 0.15 / di  # Rugosidade relativa
                Re = (ρ * v * (di / 1000)) / μ  # Número de Reynolds

                # Coeficiente de atrito
                f = sjFriction(Re, e)  # Certifique-se de importar ou definir esta função

                # Perda de carga (mca)
                Pc = (f * (Lt / (di / 1000)) * (v ** 2 / (2 * 9.81)))

                # Potência da bomba (kW)
                P_b = (ρ * (vazao_max / 3600) * Pc) / (75 * rendimento_bomba)

                # Peso do tubo (toneladas)
                esp_t = 5.48  # Espessura da parede (mm)
                de = di + 2 * esp_t  # Diâmetro externo (mm)
                A_st = np.pi * ((de ** 2 - di ** 2) / 4)  # Área transversal (mm²)
                Pe = A_st * (Lt * 1000) * 7850 / 10**9  # Peso total em toneladas

                # Cálculos de custo
                f_custoinst = Pe * custo_aco  # Custo de instalação (R$)
                f_custo_bomba = P_b * custo_energia * horas_uso  # Custo de operação anual (R$)
                custo_total_parcial = f_custoinst + f_custo_bomba + custo_valvulas + custo_acessorios

                # Armazenando resultados
                resultados.append({
                    'velocidade': f"{v:.2f}",
                    'diametro': f"{di:.2f}",
                    'reynolds': f"{Re:.2f}",
                    'coeficiente_atrito': f"{f:.4f}",
                    'perda_carga': f"{Pc:.2f}",
                    'potencia_bomba': f"{P_b:.2f}",
                    'peso_tubo': f"{Pe:.2f}",
                    'custo_instalacao': f"{f_custoinst:.2f}",
                    'custo_operacao': f"{f_custo_bomba:.2f}",
                    'custo_total_parcial': f"{custo_total_parcial:.2f}",
                })

                # Dados para gráficos
                velocidades.append(v)
                custos_totais.append(custo_total_parcial)

            except Exception as ex:
                messages.error(request, f"Erro no cálculo para velocidade {v:.2f}: {ex}")

        # Seleção do melhor resultado
        if custos_totais:
            indice_melhor_resultado = np.argmin(custos_totais)
            melhor_resultado = resultados[indice_melhor_resultado]
            di_min = float(melhor_resultado['diametro'])

            # Cálculo dos custos finais
            custos = {
                "custo_bombas": custo_bomba_unitaria * float(melhor_resultado["potencia_bomba"]),
                "custo_chiller": custo_chiller_unit * (carga_termica / cop_chiller),
                "custo_tubulacoes": custo_tubulacao_unitaria * np.pi * ((di_min / 1000) ** 2) / 4 * Lt,
                "custo_valvulas": custo_valvulas,
                "custo_acessorios": custo_acessorios,
                "custo_operacao": float(melhor_resultado["custo_operacao"]),
            }
            custo_total = sum(custos.values())

        # Gráficos
        def gerar_grafico(x, y, titulo, xlabel, ylabel):
            plt.figure()
            plt.plot(x, y, label=titulo)
            plt.xlabel(xlabel)
            plt.ylabel(ylabel)
            plt.title(titulo)
            plt.grid(True)
            buffer = BytesIO()
            plt.savefig(buffer, format="png")
            buffer.seek(0)
            grafico_base64 = base64.b64encode(buffer.getvalue()).decode("utf-8")
            buffer.close()
            plt.close()
            return grafico_base64

        curva_bomba_base64 = gerar_grafico(velocidades, custos_totais, "Curva de Custo Total", "Velocidade (m/s)", "Custo Total (R$)")

    contexto = {
        'vazao_max': vazao_max,                  # Vazão máxima calculada
        'resultados': resultados,                # Lista de resultados detalhados
        'di_min': di_min,                        # Diâmetro mínimo ideal
        'custo_total': custo_total,              # Custo total calculado
        'custos': custos,                        # Dicionário com custos detalhados
        'projeto': projeto,                      # Informações do projeto
        'curva_bomba_base64': curva_bomba_base64,
        'perda_carga_base64': perda_carga_base64,
        'custo_total_base64': custo_total_base64,
        # Valores para pré-preenchimento do formulário
        'Lp': Lp if 'Lp' in locals() else 26,
        'Ls': Ls if 'Ls' in locals() else 48,
        'carga_termica': carga_termica if 'carga_termica' in locals() else 0,
        'custo_valvulas': custo_valvulas if 'custo_valvulas' in locals() else 0,
        'custo_acessorios': custo_acessorios if 'custo_acessorios' in locals() else 0,
        'custo_bomba_unitaria': custo_bomba_unitaria if 'custo_bomba_unitaria' in locals() else 0,
        'custo_chiller_unit': custo_chiller_unit if 'custo_chiller_unit' in locals() else 0,
        'custo_tubulacao_unitaria': custo_tubulacao_unitaria if 'custo_tubulacao_unitaria' in locals() else 0,
        'cop_chiller': cop_chiller if 'cop_chiller' in locals() else 3.5,
        'horas_uso': horas_uso if 'horas_uso' in locals() else 12 * 300,
        'rendimento_bomba': rendimento_bomba * 100 if 'rendimento_bomba' in locals() else 65,
        'custo_energia': custo_energia if 'custo_energia' in locals() else 1.15,
        'custo_aco': custo_aco if 'custo_aco' in locals() else 18,
        'projeto_id': projeto_id,  # Incluído projeto_id no contexto
    }
    return render(request, 'calculocag/resultados_cag.html', contexto)
