# -*- coding: utf-8 -*-
"""
Batch Merger
Strumento per fondere layer selezionati con opzioni di proiezione e pulizia campi

Author: EagleProjects S.p.A.
"""

from qgis.core import (
    QgsProcessing,
    QgsProcessingAlgorithm,
    QgsProcessingParameterMultipleLayers,
    QgsProcessingParameterCrs,
    QgsProcessingParameterBoolean,
    QgsProcessingParameterVectorDestination,
    QgsProcessingOutputVectorLayer,
    QgsVectorLayer,
    QgsProject,
    QgsMessageLog,
    Qgis,
    QgsVectorFileWriter,
    QgsCoordinateReferenceSystem,
    QgsCoordinateTransform,
    QgsFeature,
    QgsField,
    QgsFields
)
import processing
import tempfile
import os


class BatchMergerAlgorithm(QgsProcessingAlgorithm):
    """
    Algoritmo per fondere layer selezionati con opzioni di riproiezione e pulizia campi
    """
    
    # Parametri dell'algoritmo
    INPUT_LAYERS = 'INPUT_LAYERS'
    TARGET_CRS = 'TARGET_CRS'
    REMOVE_FIELDS = 'REMOVE_FIELDS'
    OUTPUT = 'OUTPUT'

    def initAlgorithm(self, config=None):
        """
        Inizializza i parametri dell'algoritmo
        """
        # Layer multipli in input
        self.addParameter(
            QgsProcessingParameterMultipleLayers(
                self.INPUT_LAYERS,
                'Layers to merge',
                QgsProcessing.TypeVector
            )
        )
        
        # Sistema di riferimento di destinazione
        self.addParameter(
            QgsProcessingParameterCrs(
                self.TARGET_CRS,
                'Target CRS',
                defaultValue=QgsProject.instance().crs()
            )
        )
        
        # Rimuovi campi layer e path
        self.addParameter(
            QgsProcessingParameterBoolean(
                self.REMOVE_FIELDS,
                'Remove "layer" and "path" fields',
                defaultValue=True
            )
        )
        
        # Output
        self.addParameter(
            QgsProcessingParameterVectorDestination(
                self.OUTPUT,
                'Merged output'
            )
        )

    def processAlgorithm(self, parameters, context, feedback):
        """
        Esegue l'algoritmo di fusione
        """
        try:
            feedback.pushInfo("🚀 Starting Batch Merger process...")
            
            # Recupera i parametri
            input_layers = self.parameterAsLayerList(parameters, self.INPUT_LAYERS, context)
            target_crs = self.parameterAsCrs(parameters, self.TARGET_CRS, context)
            remove_fields = self.parameterAsBool(parameters, self.REMOVE_FIELDS, context)
            add_fields = not remove_fields
            output_path = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
            
            if not input_layers:
                raise ValueError("No input layers selected")
            
            feedback.pushInfo(f"📋 Processing {len(input_layers)} layers")
            feedback.pushInfo(f"🗺️ Target CRS: {target_crs.authid()}")
            feedback.pushInfo(f"📋 Add layer/path fields: {'Yes' if add_fields else 'No'}")
            
            # Usa la funzione helper
            result = run_batch_merger(input_layers, target_crs, add_fields, output_path)

            if result:
                return {self.OUTPUT: result}
            else:
                return {}
            
        except Exception as e:
            feedback.reportError(f"❌ Error in Batch Merger: {str(e)}")
            QgsMessageLog.logMessage(
                f"Batch Merger error: {str(e)}", 
                "QUtility", 
                Qgis.Critical
            )
            return {}

    def name(self):
        return 'batchmerger'

    def displayName(self):
        return 'Batch Merger'

    def group(self):
        return 'QUtility'

    def groupId(self):
        return 'qutility'

    def shortHelpString(self):
        return """
        <p><b>Batch Merger</b></p>
        <p>This tool allows you to merge selected layers with the following options:</p>
        <ul>
        <li><b>Multiple layer selection:</b> Select multiple layers to merge</li>
        <li><b>Coordinate system transformation:</b> Set target CRS for the merged output</li>
        <li><b>Field cleanup:</b> Option to remove the "layer" and "path" fields created by the merge algorithm</li>
        </ul>
        <p>The tool automatically reprojects layers to the target CRS if needed before merging.</p>
        """

    def createInstance(self):
        return BatchMergerAlgorithm()


def run_batch_merger(selected_layers, target_crs, add_fields=False, output_path=None):
    """
    Fusione dei layer usando l'algoritmo nativo di QGIS
    
    Args:
        selected_layers: Lista dei layer da fondere
        target_crs: Sistema di riferimento di destinazione  
        add_fields: Se True, mantiene i campi "layer" e "path"; se False li rimuove
        output_path: Percorso di output (opzionale)
    """
    try:
        import processing
        import tempfile
        import os
        from qgis.core import QgsProcessingFeedback, QgsVectorLayer
        
        feedback = QgsProcessingFeedback()
        
        if not selected_layers:
            raise Exception("No layers selected for merge")
        
        if not target_crs.isValid():
            raise Exception("Invalid target CRS")
        
        feedback.pushInfo(f"🚀 Starting merge of {len(selected_layers)} layers")
        feedback.pushInfo(f"📋 Add layer/path fields: {'Yes' if add_fields else 'No'}")
        
        # Crea output temporaneo se non specificato
        if not output_path:
            temp_dir = tempfile.gettempdir()
            output_path = os.path.join(temp_dir, f"batch_merger_{os.getpid()}.gpkg")
        
        # FASE 1: Riproietta i layer se necessario
        reprojected_layers = []
        
        for i, layer in enumerate(selected_layers):
            if layer.crs() != target_crs:
                feedback.pushInfo(f"🔄 Reprojecting layer {i+1}/{len(selected_layers)}: {layer.name()}")
                
                reproject_params = {
                    'INPUT': layer,
                    'TARGET_CRS': target_crs,
                    'OUTPUT': 'memory:'
                }
                
                result = processing.run("native:reprojectlayer", reproject_params, feedback=feedback)
                reprojected_layer = result['OUTPUT']
                reprojected_layers.append(reprojected_layer)
            else:
                reprojected_layers.append(layer)
        
        # FASE 2: Usa l'algoritmo nativo per il merge
        feedback.pushInfo("🔗 Merging layers with native algorithm...")
        
        merge_params = {
            'LAYERS': reprojected_layers,
            'CRS': target_crs,
            'OUTPUT': output_path
        }
        
        merge_result = processing.run("native:mergevectorlayers", merge_params, feedback=feedback)
        merged_output = merge_result['OUTPUT']
        
        # FASE 3: Se add_fields=False, rimuovi i campi "layer" e "path"
        if not add_fields:
            feedback.pushInfo("🗑️ Removing layer and path fields...")
            
            merged_layer = QgsVectorLayer(merged_output, "merged", "ogr")
            
            if merged_layer.isValid():
                fields_to_remove = []
                for field in merged_layer.fields():
                    if field.name().lower() in ['layer', 'path']:
                        fields_to_remove.append(merged_layer.fields().indexOf(field.name()))
                
                if fields_to_remove:
                    delete_params = {
                        'INPUT': merged_layer,
                        'COLUMN': fields_to_remove,
                        'OUTPUT': output_path
                    }
                    
                    processing.run("native:deletecolumn", delete_params, feedback=feedback)
                    feedback.pushInfo(f"✅ Removed {len(fields_to_remove)} fields")
        else:
            feedback.pushInfo("📋 Keeping layer and path fields as requested")
        
        feedback.pushInfo("✅ Batch merger completed successfully!")
        return output_path
        
    except Exception as e:
        feedback.reportError(f"❌ Error in batch merger: {str(e)}")
        raise e