# -*- coding: utf-8 -*-
"""
/***************************************************************************
 PandaPipesForQGISDockWidget
                                 A QGIS plugin
 An interface between the open source fluid modelling tool, Panda Pipes and QGIS.
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                             -------------------
        begin                : 2025-05-26
        git sha              : $Format:%H$
        copyright            : (C) 2025 by Thomas Raj
        email                : lemungineer@gmail.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
"""

import os

from qgis.PyQt import QtGui, QtWidgets, uic
from qgis.PyQt.QtCore import pyqtSignal
from qgis.PyQt.QtCore import QAbstractTableModel, Qt

import pandas as pd
import numpy as np

from qgis.core import (QgsVectorLayer,QgsField,QgsFields,QgsFeature,QgsGeometry,QgsPointXY,QgsProject)
from PyQt5.QtCore import QVariant
from qgis.core import QgsEditorWidgetSetup, QgsProject
from qgis.core import QgsProcessingFeatureSourceDefinition, QgsProject, QgsFeatureRequest, QgsVectorLayer, QgsMapLayerProxyModel, QgsMapLayer
from PyQt5.QtWidgets import QHeaderView
from PyQt5.QtWidgets import QTreeWidgetItem, QDialog, QMessageBox
from PyQt5.QtCore import QCoreApplication
from qgis.gui import QgsFileWidget
from openpyxl import load_workbook
import processing

from PyQt5.QtWidgets import QVBoxLayout

from .logic.assembly_functions import *

FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'assembly_manager_base.ui'))


class AssemblyManagerDialog(QDialog, FORM_CLASS):
    def __init__(self, parent=None):
        super(AssemblyManagerDialog, self).__init__(parent)
        self.setupUi(self)  # Load the UI components
        
        self.mlcbFeatureLayer.setFilters(QgsMapLayerProxyModel.PointLayer)
        
        self.fwAssemblyList.setStorageMode(QgsFileWidget.GetFile)

        script_dir = os.path.dirname(os.path.abspath(__file__))
        specifications_path = os.path.join(script_dir,'specifications','specifications.xlsx')

        self.fwAssemblyList.setFilter("Excel Workbooks (*.xlsx *.xls);;Excel Macro-Enabled (*.xlsm)")
        self.fwAssemblyList.setFilePath(specifications_path)
       
        self.mlcbFeatureLayer.layerChanged.connect(lambda layer, fc=self.fcbAssemblyField: fc.setLayer(layer if layer and layer.type() == QgsMapLayer.VectorLayer else None))
    
        # Immediately apply the logic using the current layer
        layer = self.mlcbFeatureLayer.currentLayer()
        if layer and layer.type() == QgsMapLayer.VectorLayer:
            self.fcbAssemblyField.setLayer(layer)
        else:
            self.fcbAssemblyField.setLayer(None)
    
        self.fwAssemblyList.fileChanged.connect(self.populate_sheets)
        
        self.populate_sheets()
        
        self.pbRefreshSheets.clicked.connect(self.populate_sheets)
        self.pbGenerateFittingList.clicked.connect(self.generate_fittings_list)
        
        # Updating Tree Widget
        current_layer = self.mlcbFeatureLayer.currentLayer()

        if current_layer:
            self.update_tree_fields_to_keep

        if current_layer != None:
            self.mlcbFeatureLayer.currentIndexChanged.connect(self.update_tree_fields_to_keep)
        
        self.mlcbFeatureLayer.currentIndexChanged.connect(self.update_tree_fields_to_keep)
        
    def populate_sheets(self):
        path = self.fwAssemblyList.filePath()
        
        self.cmbAssemblyListSheet.clear()
        self.cmbFilters.clear()
        self.cmbParameterList.clear()

        if not path:
            return

        try:
            wb = load_workbook(path, read_only=True)
            self.cmbAssemblyListSheet.addItems(wb.sheetnames)
            self.cmbFilters.addItems(wb.sheetnames)
            self.cmbParameterList.addItems(wb.sheetnames)
            wb.close()

        except Exception as e:
            self.iface.messageBar().pushWarning(
                "Workbook Error",
                str(e)
            )
    
    def update_tree_fields_to_keep(self):
        layer_name = self.mlcbFeatureLayer.currentLayer()
        print('CHANGE')
        print(layer_name)

        if layer_name == None:
            return
        
        if type(layer_name) == QgsVectorLayer:
            layer = layer_name
        else:
            layer = QgsProject.instance().mapLayersByName(layer_name)[0]

        self.twFieldsToKeep.clear()

        if not layer or not layer.fields():
            return

        for field in layer.fields():
            item = QTreeWidgetItem([field.name(), field.typeName()])
            item.setCheckState(0, Qt.Unchecked)  # Column 0 will have a checkbox
            self.twFieldsToKeep.addTopLevelItem(item)
    
    def generate_fittings_list(self):
        
        try:
            path = self.fwAssemblyList.filePath()
            assembly_sheet = self.cmbAssemblyListSheet.currentText()
            filter_sheet = self.cmbFilters.currentText()
            parameter_sheet = self.cmbParameterList.currentText()
            assembly_field = self.fcbAssemblyField.currentText()
            
            layer = self.mlcbFeatureLayer.currentLayer()
            
            try:
                geom_added = processing.run("native:exportaddgeometrycolumns", 
                                                    {'INPUT':layer,
                                                     'METHOD':0, # Layer CRS
                                                     'OUTPUT':'memory:'})['OUTPUT']
            except:
                geom_added = processing.run("qgis:exportaddgeometrycolumns", 
                                                    {'INPUT':layer,
                                                     'METHOD':0, # Layer CRS
                                                     'OUTPUT':'memory:'})['OUTPUT']
            
            fittings_df = layer_to_df(layer=geom_added)
            
            parameter_df = pd.read_excel(path,sheet_name=parameter_sheet)
            
            parameters = parameter_df['parameter'].tolist()
            fittings_df = add_max_min_mode(df=fittings_df,parameters=parameters)
            
            assembly_list_df = pd.read_excel(path,sheet_name=assembly_sheet)
            filters_df = pd.read_excel(path,sheet_name=filter_sheet)
            
            features = parameter_df['parameter'].tolist()
            
            mto_df = return_mto(project_data_df=fittings_df,assembly_field=assembly_field,assembly_list_df=assembly_list_df,filters_df=filters_df,features=features)
            
            script_dir = os.path.dirname(os.path.abspath(__file__))
            script_dir = os.path.dirname(os.path.abspath(__file__))
            working_folder = os.path.join(script_dir,'working')
            os.makedirs(working_folder, exist_ok=True)
            
            df_save_path = os.path.join(working_folder,'fitting_list.csv')
            
            mto_df.to_csv(df_save_path,index=False)
            
            layer_crs = layer.crs()
            
            uri = (f"file:///{df_save_path}""?delimiter=,&xField=xcoord&yField=ycoord"f"&crs={layer_crs.authid()}")

            fitting_layer = QgsVectorLayer(uri, 'Fittings','delimitedtext')
            
            field_names = [field.name() for field in layer.fields()]
            
            fields_to_keep = []

            for i in range(self.twFieldsToKeep.topLevelItemCount()):
                item = self.twFieldsToKeep.topLevelItem(i)
                if item.checkState(0) == Qt.Checked:
                    field_name = item.text(0)  # Assuming the field name is in column 0
                    fields_to_keep.append(field_name)
            
            fields_to_drop = [x for x in field_names if x not in fields_to_keep]
            fields_to_drop.extend(['xcoord','ycoord'])
            
            fields_dropped = processing.run("native:deletecolumn", 
                                                        {'INPUT':fitting_layer,
                                                         'COLUMN':fields_to_drop,
                                                         'OUTPUT':'memory:'})['OUTPUT']

            fields_dropped.setName(f'{layer.name()} Fittings')
            QgsProject.instance().addMapLayer(fields_dropped)
        finally:
            
            self.accept()