# -*- 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.core import QgsProject, QgsVectorLayer, QgsField, QgsFeature, QgsGeometry, QgsPointXY, QgsRaster
from qgis.PyQt.QtCore import QStandardPaths
from qgis.PyQt.QtCore import QVariant
from .Sewercalc_Estilo import aplicar_estilo
import numpy as np
import json
import os


def pontos_criticos(camada_rede, camada_mde, configuracoes, tabela_pv, tabela_rede):
    layer_mde = QgsProject.instance().mapLayer(camada_mde)
    layer_rede = QgsProject.instance().mapLayer(camada_rede)

    def encontrar_id(nome_pv):
        for id_pv, dados in tabela_pv.items():
            if dados['NOME'] == nome_pv:
                return id_pv
        return None

    def converter_valor(valor):
        if isinstance(valor, QVariant):
            return valor if valor.isValid() else None
        return valor


    def obter_cotas_terreno(geom, passo):
        comprimento_geom = geom.length()
        interpol_x = np.arange(0, comprimento_geom + passo, passo)
        cotas_dict = {}

        for x in interpol_x:
            ponto = geom.interpolate(x)
            if not ponto or ponto.isEmpty():
                continue

    
            ident = layer_mde.dataProvider().identify(ponto.asPoint(), QgsRaster.IdentifyFormatValue)
            if not ident.isValid():
                continue
                
            cota = None
            if hasattr(ident, 'results'):
                results = ident.results()
                if results:
                    cota = list(results.values())[0] if results else None
            else:
                cota = ident.value(1)

            if cota is not None:
                cotas_dict[float(cota)] = {
                    'xy': ponto.asPoint(),
                    'L': float(x)
                }

        return cotas_dict

    pontos_criticos = {}
    for feicao_id, col in tabela_rede.items():
        pontos_criticos_trecho = {}
        pv_mont = col['PV_MONT']
        pv_jus = col['PV_JUS']
        nome = col['NOME']

        id_pv_mont = encontrar_id(pv_mont)
        id_pv_jus = encontrar_id(pv_jus)

        CFM = converter_valor(tabela_pv[id_pv_mont]['CTF'])
        DN = converter_valor(col['DN'])
        i = converter_valor(col['i'])
        Rmin = float(configuracoes.get("Edit_R_min", 0))

        # Verificar valores nulos
        if None in [CFM, DN, i]:
            continue

        geom = None
        for trecho in layer_rede.getFeatures():
            if trecho.id() == feicao_id:
                geom = trecho.geometry()
                break

        if geom and geom.length() > 0:
            tab_cotas = obter_cotas_terreno(geom, passo=1)

            if tab_cotas:
                for cota, info in tab_cotas.items():
                    try:
                        CT_L = float(cota)
                        L = float(info['L'])
                        xy = info['xy']

                        CF_L = float(CFM) - (L * float(i))
                        PFJ_L = CT_L - CF_L
                        RJ_L = PFJ_L - float(DN)

                        if round(RJ_L, 2) < Rmin:
                            ponto_critico = {
                                'cota': round(CT_L, 3),
                                'trecho': nome,
                                'trecho_id': feicao_id,
                                'CF_L': round(CF_L, 3),
                                'PFJ_L': round(PFJ_L, 3),
                                'RJ_L': round(RJ_L, 3),
                                'L': round(L, 3),
                                'xy': xy
                            }
                            pontos_criticos_trecho[RJ_L] = ponto_critico
                    except (TypeError, ValueError) as e:
                        continue

                if pontos_criticos_trecho:
                    menor_cota = min(pontos_criticos_trecho.keys())
                    info_menor_cota = pontos_criticos_trecho[menor_cota]
                    pontos_criticos[nome] = info_menor_cota

    #------------------Criando pontos-------------------
    crs_rede = layer_rede.crs().authid()
    pontos_criticos_layer = QgsVectorLayer(f"Point?crs={crs_rede}", "Pontos Críticos", "memory")
    provider = pontos_criticos_layer.dataProvider()
    provider.addAttributes([QgsField("TRECHO", QVariant.String),
                           QgsField("CT", QVariant.Double),
                           QgsField("CF", QVariant.Double),
                           QgsField("PF", QVariant.Double),
                           QgsField("REC", QVariant.Double),
                           QgsField("L", QVariant.Double)])
    pontos_criticos_layer.updateFields()

    for key, ponto in pontos_criticos.items():
        feat = QgsFeature()
        feat.setGeometry(QgsGeometry.fromPointXY(ponto['xy']))
        feat.setAttributes([ponto['trecho'],
                           ponto['cota'],
                           ponto['CF_L'],
                           ponto['PFJ_L'],
                           ponto['RJ_L'],
                           ponto['L']])
        provider.addFeature(feat)
    pontos_criticos_layer.updateExtents()
    QgsProject.instance().addMapLayer(pontos_criticos_layer)

    #salvando tabela------------------------
    pontos_criticos2 = {}
    pontos_criticos2 = {
        key: {k: v for k, v in value.items() if k != 'xy'}
        for key, value in pontos_criticos.items()
    }

    # Converter os valores para formato serializável
    pontos_criticos_convertido = {}
    for key, value in pontos_criticos2.items():
        pontos_criticos_convertido[key] = {
            k: converter_valor(v) for k, v in value.items()
        }


    # Obter o caminho---------------------------------------------------
    config_dir = QStandardPaths.writableLocation(QStandardPaths.AppDataLocation)
    os.makedirs(config_dir, exist_ok=True) 
    arquivo_path = os.path.join(config_dir, "pontos_criticos.json")
        
    temp_path = arquivo_path + '.tmp'
       
    #Salvar os dados
    with open(temp_path, 'w', encoding='utf-8') as f:
        json.dump(pontos_criticos_convertido, f, indent=4, ensure_ascii=False)
        
    #Substituir o arquivo original
    if os.path.exists(temp_path):
        os.replace(temp_path, arquivo_path)
    
    aplicar_estilo(pontos_criticos_layer.id(), "Estilo Pnt_C.qml")
    