from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsProcessing,
                       QgsProcessingAlgorithm,
                       QgsProcessingParameterFeatureSource,
                       QgsProcessingParameterFile,
                       QgsProcessingParameterField,
                       QgsProcessingParameterNumber,
                       QgsProcessingParameterFileDestination,
                       QgsProcessingException)
import csv

class TransferCsvField(QgsProcessingAlgorithm):
    
    INPUT_LAYER = 'INPUT_LAYER'
    INPUT_CSV = 'INPUT_CSV'
    LAYER_FIELD_I = 'LAYER_FIELD_I'
    LAYER_FIELD_J = 'LAYER_FIELD_J'
    SOURCE_DATA_FIELD = 'SOURCE_DATA_FIELD'
    CSV_INDEX_I = 'CSV_INDEX_I'
    CSV_INDEX_J = 'CSV_INDEX_J'
    CSV_INDEX_TARGET = 'CSV_INDEX_TARGET'
    OUTPUT_CSV = 'OUTPUT_CSV'

    def tr(self, string):
        return QCoreApplication.translate('TransferCsvField', string)

    def createInstance(self):
        return TransferCsvField()

    def name(self):
        return 'updatecsvsafe'

    def displayName(self):
        return self.tr('Transfer CSV field by index')

    def group(self):
        return self.tr('Utilities')

    def groupId(self):
        return 'Utilities'

    def initAlgorithm(self, config=None):
        # Configuration des paramètres (identique à précédemment)
        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT_LAYER, self.tr('Qgis layer')))
        self.addParameter(QgsProcessingParameterField(self.LAYER_FIELD_I, self.tr('"i" field (QGIS)'), 'i', self.INPUT_LAYER))
        self.addParameter(QgsProcessingParameterField(self.LAYER_FIELD_J, self.tr('"j" field(QGIS)'), 'j', self.INPUT_LAYER))
        self.addParameter(QgsProcessingParameterField(self.SOURCE_DATA_FIELD, self.tr('field to copy'), None, self.INPUT_LAYER))

        self.addParameter(QgsProcessingParameterFile(self.INPUT_CSV, self.tr('CSV source file'), extension='txt'))
        self.addParameter(QgsProcessingParameterNumber(self.CSV_INDEX_I, self.tr('col "i" index (CSV)'), defaultValue=0))
        self.addParameter(QgsProcessingParameterNumber(self.CSV_INDEX_J, self.tr('col "j" index (CSV)'), defaultValue=1))
        self.addParameter(QgsProcessingParameterNumber(self.CSV_INDEX_TARGET, self.tr('target col (CSV)'), defaultValue=2))

        self.addParameter(QgsProcessingParameterFileDestination(self.OUTPUT_CSV, self.tr('CSV output file'), 'TXT files (*.txt)'))

    def processAlgorithm(self, parameters, context, feedback):
        layer = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
        csv_path = self.parameterAsFile(parameters, self.INPUT_CSV, context)
        output_path = self.parameterAsFileOutput(parameters, self.OUTPUT_CSV, context)
        
        l_i, l_j, l_src = self.parameterAsString(parameters, self.LAYER_FIELD_I, context), \
                          self.parameterAsString(parameters, self.LAYER_FIELD_J, context), \
                          self.parameterAsString(parameters, self.SOURCE_DATA_FIELD, context)
        
        c_i, c_j, c_target = self.parameterAsInt(parameters, self.CSV_INDEX_I, context), \
                             self.parameterAsInt(parameters, self.CSV_INDEX_J, context), \
                             self.parameterAsInt(parameters, self.CSV_INDEX_TARGET, context)

        # 1. Indexation de la couche
        data_map = { (str(f[l_i]), str(f[l_j])): f[l_src] for f in layer.getFeatures() }

        # 2. Traitement du CSV
        try:
            with open(csv_path, mode='r', encoding='utf-8') as f_in:
                reader = csv.reader(f_in, delimiter=';')
                rows = list(reader)

            with open(output_path, mode='w', encoding='utf-8', newline='') as f_out:
                writer = csv.writer(f_out, delimiter=';')
                
                for i, row in enumerate(rows):
                    # --- LE TEST DE SÉCURITÉ ---
                    # Si la ligne est vide (souvent le cas en fin de fichier), on l'ignore ou on la laisse vide
                    if not row:
                        writer.writerow(row)
                        continue

                    # On détermine la longueur minimale requise pour cette ligne
                    required_length = max(c_i, c_j, c_target) + 1
                    
                    # Si la ligne est trop courte, on l'étend avec des chaînes vides
                    if len(row) < required_length:
                        row.extend([''] * (required_length - len(row)))

                    # Extraction de la clé et mise à jour
                    csv_key = (str(row[c_i]), str(row[c_j]))
                    if csv_key in data_map:
                        row[c_target] = data_map[csv_key]
                    
                    writer.writerow(row)
                    
                    # Feedback optionnel pour les gros fichiers
                    if feedback.isCanceled(): break

        except Exception as e:
            raise QgsProcessingException(self.tr(f"Processing error : {str(e)}"))

        return {self.OUTPUT_CSV: output_path}