# -*- coding: utf-8 -*-
"""
/***************************************************************************
 Sewercalc
                                 A QGIS plugin
 Plugin para dimensionamento de redes coletoras de esgoto 
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2025-02-07
        git sha              : $Format:%H$
        copyright            : (C) 2025 by Wanderilo  Lima
        email                : Wanderilo Lima
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""



from qgis.PyQt.QtCore import QTimer
from qgis.utils import iface
from qgis.PyQt.QtCore import QStandardPaths
from qgis.core import QgsProject, QgsRaster, Qgis, QgsProcessingException
from .Sewercalc_Informacoes import verificar_camadas
import numpy as np
import matplotlib.pyplot as plt
from .Sewercalc_config_cx_txt import carregar_configuracoes
import os
import json


def carregar_json(nome_arquivo):
    try:
        config_dir = QStandardPaths.writableLocation(QStandardPaths.AppDataLocation)
        caminho_arquivo = os.path.join(config_dir, nome_arquivo)
        
        if os.path.exists(caminho_arquivo):
            with open(caminho_arquivo, 'r', encoding='utf-8') as f:
                return json.load(f)
        return {}  # Retorna dict vazio se o arquivo não existir
        
    except json.JSONDecodeError:
        print(f"ERRO: Arquivo {nome_arquivo} corrompido")
        return {}
    except PermissionError:
        print(f"ERRO: Sem permissão para ler {nome_arquivo}")
        return {}
    except Exception as e:
        print(f"ERRO ao carregar {nome_arquivo}: {str(e)}")
        return {}
    
def verificar_tabela():
    tabela_pv = carregar_json("tabela_pv.json")
    tabela_rede = carregar_json("tabela_rede.json")
    
    if not tabela_pv or not tabela_rede:  
        iface.messageBar().pushMessage(
            "Pré-requisito necessário",  
            "❌ É necessário realizar o dimensionamento antes de exibir o perfil da rede.",
            level=Qgis.Critical,
            duration=5
        )
        return 1

def lista_coletores(dlg_perfil):
    coletores_unicos = set()
    tabela_rede = carregar_json("tabela_rede.json")
    
    for dados in tabela_rede.values():
        coletores_unicos.add(dados['COLETOR'])
        
    lista_coletores = sorted(coletores_unicos)
    dlg_perfil.List_Coletores.clear()
    dlg_perfil.List_Coletores.addItems(map(str, lista_coletores))

def grafico(coletor, terreno_MDE, exibir_pc, zoom_coletor):
    
    #-------------------------------------------------
    camadas_verificar = ["MDE", "PV"]
    nao_encontradas = verificar_camadas(camadas_verificar)
    
    if nao_encontradas:  
        camadas_faltantes = "\n• " + "\n• ".join(nao_encontradas) 
        iface.messageBar().pushMessage(
            "Erro: Camadas faltantes", 
            f"As seguintes camadas não foram encontradas:{camadas_faltantes}",
            level=Qgis.Critical, 
            duration=10 
        )
        return
    #-------------------------------------------------


    coletor = int(coletor)
    tabela_pv  = {}
    tabela_rede = {}
    pontos_criticos = {}
    tabela_pv = carregar_json("tabela_pv.json")
    tabela_rede = carregar_json("tabela_rede.json")
    pontos_criticos = carregar_json("pontos_criticos.json")
    
    
    configuracoes = carregar_configuracoes()

    camada_mde = configuracoes.get("camada_mde") 
    camada_rede = configuracoes.get("camada_rede")

    L1 = 0
    Larg_PV = 0.8
    passo = 1
    coletor_escolhido = {k: v for k, v in tabela_rede.items() if v["COLETOR"] == coletor}
    coletor_ordenado = dict(sorted(coletor_escolhido.items(), key=lambda item: item[1]["TRECHO"]))
    
    def encontrar_id(nome_pv):
        for id_pv, dados in tabela_pv.items():
            if dados["NOME"] == nome_pv:
                return id_pv
        return None

    
    camada_rede_layer = QgsProject.instance().mapLayer(camada_rede)
    camada_mde_layer = QgsProject.instance().mapLayer(camada_mde)

    plt.figure(figsize=(12, 6)) 
    legendas = set()

    if zoom_coletor == "SIM":
        fontsize = 7
    else:
        fontsize = 8

    # limites do zoom inicial----------
    primeiro_trecho_x1 = None
    primeiro_trecho_x2 = None
    primeiro_trecho_y_min = None
    primeiro_trecho_y_max = None

    def obter_cotas_terreno(geom, passo):
        comprimento_geom = geom.length()
        interpol_x = np.arange(0, comprimento_geom + passo, passo)
        cota_terreno = []
        
        for x in interpol_x:
            ponto = geom.interpolate(x)
            if not ponto or ponto.isEmpty():
                cota_terreno.append(None)
                continue
            
            ident = camada_mde_layer.dataProvider().identify(ponto.asPoint(), QgsRaster.IdentifyFormatValue)
            results = ident.results() if ident else None
            
            if results and 1 in results:
                cota = results[1]
            else:
                cota = None
            
            cota_terreno.append(cota)
        
        return interpol_x, cota_terreno

    for feicao_id, col in coletor_ordenado.items():  
        L2 = col["L"]
        DN = col["DN"]
        Y = col["Y_FIM"]
        CTM = col["CTM"]
        CTJ = col["CTJ"]
        PFM = col["PFM"]
        PFJ = col["PFJ"]
        I0 = col['i']  
        NOME_REDE = col['NOME'] 
        pv_mont = col["PV_MONT"]
        pv_jus = col["PV_JUS"]

        id_pv_mont = encontrar_id(pv_mont)
        id_pv_jus = encontrar_id(pv_jus)
        
        PF_PVM = tabela_pv[id_pv_mont]["PF"]
        PF_PVJ = tabela_pv[id_pv_jus]["PF"]
        NOME_PVM = tabela_pv[id_pv_mont]['NOME'] 
        NOME_PVJ = tabela_pv[id_pv_jus]['NOME'] 

        PF_PV1 = CTM - PF_PVM  
        PF_PV2 = CTJ - PF_PVJ  

        PF_REDE1 = CTM - PFM
        PF_REDE2 = CTJ - PFJ
        
        pv1_x = L1
        pv2_x = L1 + L2
                
        # ponto critico------------------------
        if exibir_pc == "SIM":   
            for ponto, info in pontos_criticos.items():
                if info['trecho_id'] == int(feicao_id):
                    ponto_rec = info['RJ_L']
                    ponto_cota = info['cota']
                    ponto_L = info['L']

                    # pontos criticos ---------------------
                    plt.text(pv1_x + ponto_L, ponto_cota + 0.07, f"Rec.: {ponto_rec}", color='black', fontsize=fontsize, ha='left', va='bottom', fontweight='normal')
                    
                    # Plotar o ponto crítico
                    plt.scatter(pv1_x + ponto_L, ponto_cota, color='red', s=80, zorder=6)
                    
                    # Adicionar à legenda apenas uma vez
                    if "Ponto Crítico" not in legendas:
                        plt.scatter([], [], color='red', s=80, label="Ponto Crítico")  
                        legendas.add("Ponto Crítico") 

        # Definir os limites do zoom inicial------------------------
        if primeiro_trecho_x1 is None:
            primeiro_trecho_x1 = pv1_x
            primeiro_trecho_x2 = pv2_x
            primeiro_trecho_y_min = min(PF_PV1, PF_PV2)  #  (fundo do PV)
            primeiro_trecho_y_max = max(CTM, CTJ)  # (tampa do PV)
        
        min_limite_y = 0
        if PF_REDE2 > min_limite_y:
            min_limite_y = PF_REDE2

        # Representando o terreno natural-----------
        if terreno_MDE == "SIM":
            geom = None
            for feat in camada_rede_layer.getFeatures():
                if feat["NOME"] == NOME_REDE: 
                    geom = feat.geometry()
                    break
            
            if geom:
                interpol_x, cota_terreno = obter_cotas_terreno(geom, passo)
                x_plot = pv1_x + interpol_x
                if len(x_plot) > 0 and len(cota_terreno) > 0:
                    # Preenche valores None com a última cota válida--------------
                    ultima_cota_valida = None
                    for i in range(len(cota_terreno)):
                        if cota_terreno[i] is not None:
                            ultima_cota_valida = cota_terreno[i]
                        elif ultima_cota_valida is not None:
                            cota_terreno[i] = CTJ
                    
                    # Desenha o terreno natural---------------
                    if "Terreno Natural (MDE)" not in legendas:
                        plt.plot(x_plot, cota_terreno, color="saddlebrown", linewidth=2, label="Terreno Natural (MDE)")
                        legendas.add("Terreno Natural (MDE)")
                    else:
                        plt.plot(x_plot, cota_terreno, color="saddlebrown", linewidth=2)
        else:
            # Desenha o terreno natural como uma linha reta --------------------
            if "Terreno Natural" not in legendas:
                plt.plot([pv1_x + (Larg_PV / 2), pv2_x - (Larg_PV / 2)], [CTM, CTJ], color="saddlebrown", linewidth=2, label="Terreno Natural")
                legendas.add("Terreno Natural")
            else:
                plt.plot([pv1_x + (Larg_PV / 2), pv2_x - (Larg_PV / 2)], [CTM, CTJ], color="saddlebrown", linewidth=2)

        # Poços de visita -----------------------
        if "PV" not in legendas:
            # PV Inicial
            plt.plot([pv1_x - (Larg_PV / 2), pv1_x - (Larg_PV / 2)], [CTM, PF_PV1], color='blue', linewidth=2, label="PV")  # Parede esquerda
            plt.plot([pv1_x + (Larg_PV / 2), pv1_x + (Larg_PV / 2)], [CTM, PF_PV1], color='blue', linewidth=2)  # Parede direita
            plt.plot([pv1_x - (Larg_PV / 2), pv1_x + (Larg_PV / 2)], [CTM, CTM], color='blue', linewidth=2)  # Tampa
            plt.plot([pv1_x - (Larg_PV / 2), pv1_x + (Larg_PV / 2)], [PF_PV1, PF_PV1], color='blue', linewidth=2)  # Fundo
            legendas.add("PV")
        else:
            # PV Inicial-------------------
            plt.plot([pv1_x - (Larg_PV / 2), pv1_x - (Larg_PV / 2)], [CTM, PF_PV1], color='blue', linewidth=2)  # Parede esquerda
            plt.plot([pv1_x + (Larg_PV / 2), pv1_x + (Larg_PV / 2)], [CTM, PF_PV1], color='blue', linewidth=2)  # Parede direita
            plt.plot([pv1_x - (Larg_PV / 2), pv1_x + (Larg_PV / 2)], [CTM, CTM], color='blue', linewidth=2)  # Tampa
            plt.plot([pv1_x - (Larg_PV / 2), pv1_x + (Larg_PV / 2)], [PF_PV1, PF_PV1], color='blue', linewidth=2)  # Fundo

        # PV Final-----------------------
        plt.plot([pv2_x - (Larg_PV / 2), pv2_x - (Larg_PV / 2)], [CTJ, PF_PV2], color='blue', linewidth=2)  # Parede esquerda
        plt.plot([pv2_x + (Larg_PV / 2), pv2_x + (Larg_PV / 2)], [CTJ, PF_PV2], color='blue', linewidth=2)  # Parede direita
        plt.plot([pv2_x - (Larg_PV / 2), pv2_x + (Larg_PV / 2)], [CTJ, CTJ], color='blue', linewidth=2)  # Tampa
        plt.plot([pv2_x - (Larg_PV / 2), pv2_x + (Larg_PV / 2)], [PF_PV2, PF_PV2], color='blue', linewidth=2)  # Fundo

        # Nome dos PVs acima da tampa--------------------------
        plt.text(pv1_x, CTM + 0.05, f"{NOME_PVM} \n {round(PF_PVM,2)}m", color='black', fontsize=fontsize, ha='center', va='bottom', fontweight='bold')  # Nome do PV montante
        plt.text(pv2_x, CTJ + 0.05, f"{NOME_PVJ} \n {round(PF_PVJ,2)}m", color='black', fontsize=fontsize, ha='center', va='bottom', fontweight='bold')  # Nome do PV jusante
    

        
        
        # Linhas da tubulação ---------------------
        tubo_x = np.linspace(pv1_x, pv2_x, 100)
        tubo_y = np.interp(tubo_x, [pv1_x, pv2_x], [PF_REDE1, PF_REDE2])

        if "Tubulação" not in legendas:
            plt.plot(tubo_x, tubo_y, color="darkgreen", linewidth=2, label="Tubulação")
            plt.plot(tubo_x, tubo_y + DN, color="darkgreen", linewidth=2)
            legendas.add("Tubulação")
        else:
            plt.plot(tubo_x, tubo_y, color="darkgreen", linewidth=2)
            plt.plot(tubo_x, tubo_y + DN, color="darkgreen", linewidth=2)

        # Linha da lâmina d'água-----------------------------
        Y_y = tubo_y + Y
        if "Lâmina de Esgoto" not in legendas:
            plt.plot(tubo_x, Y_y, color="black", linestyle="--", linewidth=0.8, label="Lâmina de Esgoto")
            legendas.add("Lâmina de Esgoto")
        else:
            plt.plot(tubo_x, Y_y, color="black", linestyle="--", linewidth=0.8)

        # Preenchimento da área de esgoto-------------------------
        if "Esgoto" not in legendas:
            plt.fill_between(tubo_x, Y_y, tubo_y, color="orange", alpha=0.5, label="Esgoto")
            legendas.add("Esgoto")
        else:
            plt.fill_between(tubo_x, Y_y, tubo_y, color="orange", alpha=0.5)

        # Legenda abaixo da tubulação (inclinada e em negrito)---------------------
        ponto_medio_x = (pv1_x + pv2_x) / 2  # Ponto médio do trecho
        ponto_medio_y = np.interp(ponto_medio_x, [pv1_x, pv2_x], [PF_REDE1, PF_REDE2])  # Coordenada Y na tubulação
        angulo_inclinacao = np.degrees(np.arctan(-(0)))  #  ângulo de inclinação
        DN_mm = int(DN * 1000)
        legenda_trecho = f"{L2}m - DN{DN_mm} - {I0:.4f}"

        # Nome da rede (afastado verticalmente)------------------
        plt.text(ponto_medio_x, ponto_medio_y - 0.3, NOME_REDE, color='black', fontsize=fontsize, ha='center', va='top', fontweight='bold', rotation=angulo_inclinacao)

        # Legenda do trecho (comprimento, DN, inclinação)--------------------
        plt.text(ponto_medio_x, ponto_medio_y - 0.6, legenda_trecho, color='black', fontsize=fontsize, ha='center', va='top', fontweight='bold', rotation=angulo_inclinacao)

        L1 += L2

    # Personalização do gráfico----------------
    plt.title(f"Perfil do Coletor {coletor}", fontweight='bold') 
    plt.xlabel("Distância (m)", fontweight='bold') 
    plt.ylabel("Altura (m)", fontweight='bold') 
    plt.axhline(0, color="black", linewidth=0.5, linestyle="--")
    plt.grid(True)
    plt.legend(loc='upper right', prop={'weight': 'bold'}) 
    plt.tight_layout()  

    margem_x = 1.0  
    margem_y = 0.5 

    if zoom_coletor == "SIM":
        plt.gca().autoscale(enable=True, tight=True) 
        ax = plt.gca()
        x_min, x_max = ax.get_xlim()
        y_min, y_max = ax.get_ylim()
        
        # Aplica as margens MANUALMENTE (garantido)
        ax.set_xlim(x_min - margem_x, x_max + margem_x)
        ax.set_ylim(min_limite_y - margem_y, y_max + margem_y)

    else:
        plt.xlim(primeiro_trecho_x1 - (Larg_PV/2) - margem_x, primeiro_trecho_x2 + (Larg_PV/2) + margem_x)
        plt.ylim(primeiro_trecho_y_min - margem_y, primeiro_trecho_y_max + margem_y)

    plt.tight_layout()
    plt.show()