import { MatDialogRef } from '@angular/material/dialog';
import { EquipmentLruUploadComponent } from '../equipment-lru-upload/equipment-lru-upload.component';
import { Component, ElementRef, Inject, input, OnInit, output, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatTableDataSource } from '@angular/material/table';
import { FunctionsService } from '../../../services/functions.service';
import { TempFileInfo } from '../../../interfaces/temp-file-info.interface';
import { ResourcesService } from '../../../services/resources.service';
import { lastValueFrom, zip } from 'rxjs';
import { GdelService } from '../../../services/gdel.service';
import * as XLSX from 'xlsx';
import { FormControl, Validators } from '@angular/forms';
import JSZip from 'jszip';
import { PreviewDocumentsComponent } from '../preview-documents/preview-documents.component';
import { PreviewFileContentComponent } from '../preview-file-content/preview-file-content.component';

const ID_MODULE = "S002V01M15IDUP";

export interface Document {
  nombre_del_archivo: string,
  tamano_del_archivo: string,
  archivo_id?: string,
  tipo_archivo?: string,
  fecha_carga?: string
}


export interface ProcessedDocument {
  nombre_del_archivo: string;
  tamano_del_archivo: string;
  archivo_id: string;
  tipo_archivo: string;
  fecha_carga: string;
  estado: 'temp_uploaded' | 'final_saved' | 'error';
  error_message?: string;
}

export interface ZipFileEntry {
  name: string;
  size: number;
  isDirectory: boolean;
  content?: string | Uint8Array;
  type?: string;
}


export interface DocumentValidationResult {
  isValid: boolean;
  foundFiles: string[];
  missingFiles: string[];
  extraFiles: string[];
  validationDetails: {
    expectedCount: number;
    foundCount: number;
    matchedCount: number;
  };
}

export interface ExcelDocumentEntry {
  rowIndex: number;
  columnLetter: string;
  columnIndex: number;
  documentName: string;
  category: string;
}

interface SheetHeaderStructure {
  [column: string]: string;
}

interface TemplateStructure {
  [sheetName: string]: SheetHeaderStructure;
}

@Component({
  selector: 'app-zipfile-upload',
  standalone: false,
  templateUrl: './zipfile-upload.component.html',
  styleUrl: './zipfile-upload.component.css'
})
export class ZipfileUploadComponent {

private originalZipFile: File | null = null;
  
public processedDocuments: ProcessedDocument[] = [];
  public isLoading: boolean = false;
  public hasError: boolean = false;
  public errorMessage: string = '';
  public isUploading: boolean;
  public currentFileType: 'excel' | 'zip' | null = null;

  uploadedFile: TempFileInfo | null;
  @ViewChild('file') private uploader?: ElementRef;

  moduleControl = new FormControl('', Validators.required);

  public dataSource: MatTableDataSource<Document>;
  public displayedColumns: string[] = ['nombre_del_archivo', 'tamano_del_archivo', 'tipo_archivo', 'acciones'];
  
  // Variables para manejar archivos Excel 
  public excelFile: Document | null = null;
  public excelData: any = null;

  // Variables para manejar archivos ZIP
  public zipFile: Document | null = null;
  public zipData: { 
    fileName: string; 
    files: ZipFileEntry[]; 
    fileId: string;
    totalFiles: number;
    totalSize: number;
  } | null = null;

  // Variables para drag and drop
  public isDragOver: boolean = false;

  // Configuración específica para archivos Excel
  private readonly EXCEL_EXTENSIONS = ['xlsx', 'xls'];
  private readonly MAX_FILE_SIZE_MB = 10;
  private readonly HEADER_ROW = 7; 
  
  // Configuración específica para archivos zip
  private readonly ZIP_EXTENSIONS = ['zip'];
  private readonly MAX_ZIP_SIZE_MB = 250; 

  // Estructura de la plantilla esperada
  private readonly TEMPLATE_STRUCTURE: TemplateStructure = {
    'CARGA DE DOCUMENTOS': {
      'B': 'CÓDIGO EQUIVALENTE',
      'D': 'CÓDIGO DE EQUIPO',
      'F': 'CÓDIGO DEL LRU',
      'H': 'FICHA DE SEGURIDAD DE PRODUCTOS QUÍMICOS',
      'J': 'FICHA TÉCNICA',
      'L': 'FOTOGRAFÍAS - DIAGRAMAS',
      'N': 'DATOS DEL PROVEEDOR',
      'P': 'MANUALES DE OPERACIÓN',
      'R': 'MANUALES DE MANTENIMIENTO PREVENTIVO',
      'T': 'MANUALES DE MANTENIMIENTO CORRECTIVO',
      'V': 'DOCUMENTOS ADICIONALES'
     }
  };

  // Hojas requeridas en la plantilla
  private readonly REQUIRED_SHEETS = ['CARGA DE DOCUMENTOS'];

  constructor (
    private dialogRef: MatDialogRef<EquipmentLruUploadComponent>,
    private _gdelService: GdelService,
    private _matDialog: MatDialog,
    private _functionService: FunctionsService,
    private _resourcesService: ResourcesService,
  ) {
    this.isLoading = false;
    this.isUploading = false;
    this.uploadedFile = null;
    this.dataSource = new MatTableDataSource();
  }

  ngOnInit(): void {
    this.loadFiles();
  }

  cancelar(): void {
    this.dialogRef.close();
  }

  openFileUploader(): void {
    this.uploader?.nativeElement.click();
  }


  onDragOver(event: DragEvent): void {
    event.preventDefault();
    event.stopPropagation();
    this.isDragOver = true;
  }

  onDragLeave(event: DragEvent): void {                           
    event.preventDefault();
    event.stopPropagation();
    this.isDragOver = false;
  }

  onDrop(event: DragEvent): void {
    event.preventDefault();
    event.stopPropagation();
    this.isDragOver = false;

    const files = event.dataTransfer?.files;
    if (files && files.length > 0) {
      this.processFile(files[0]);
    }
  }

  checkFile(event: any): void {
    const file = event.target.files[0];
    if (!file) return;
    this.processFile(file);
  }

  private processFile(file: File): void {
    const fileName = file.name.toLowerCase();
    const fileExtension = fileName.split('.').pop();
    
    if (!fileExtension) {
      this._resourcesService.openSnackBar('Archivo sin extensión válida');
      return;
    }

    // Determinar el tipo de archivo y validar
    if (this.EXCEL_EXTENSIONS.includes(fileExtension)) {
      if (!this.isValidFileSize(file, this.MAX_FILE_SIZE_MB)) return;
      this.currentFileType = 'excel';
      this.isUploading = true;
      this.uploadExcelFile(file);
    } else if (this.ZIP_EXTENSIONS.includes(fileExtension)) {
      if (!this.isValidFileSize(file, this.MAX_ZIP_SIZE_MB)) return;
      this.currentFileType = 'zip';
      this.isUploading = true;
      this.uploadZipFile(file);
    } else {
      this._resourcesService.openSnackBar('Solo se permiten archivos Excel (.xlsx, .xls) o ZIP (.zip)');
    }
  }

  private isValidFileSize(file: File, maxSizeMB: number): boolean {
    const maxFileSize = maxSizeMB * 1024 * 1024;
    
    if (file.size > maxFileSize) {
      this._resourcesService.openSnackBar(`El tamaño del archivo supera el límite de ${maxSizeMB} MB`);
      return false;
    }
    
    return true;
  }

  // Método para validar la estructura de la plantilla Y que tenga datos
  private validateExcelTemplate(workbook: XLSX.WorkBook): { isValid: boolean, errors: string[] } {
    const errors: string[] = [];
    
    // Verificar que existan todas las hojas requeridas
    const existingSheets = workbook.SheetNames;
    const missingSheets = this.REQUIRED_SHEETS.filter(sheet => !existingSheets.includes(sheet));
    
    if (missingSheets.length > 0) {
      errors.push(`Tu documento no cumple con las hojas requeridas de la plantilla`);
    }

    // Validar headers de cada hoja Y verificar que tengan datos
    for (const sheetName of this.REQUIRED_SHEETS) {
      if (existingSheets.includes(sheetName)) {
        const sheetErrors = this.validateSheetHeaders(workbook.Sheets[sheetName], sheetName);
        errors.push(...sheetErrors);
        
        if (sheetName === 'CARGA DE DOCUMENTOS') {
          const dataErrors = this.validateSheetHasData(workbook.Sheets[sheetName], sheetName);
          errors.push(...dataErrors);
        }
      }
    }

    return {
      isValid: errors.length === 0,
      errors: errors
    };
  }

  // Nuevo método para validar que una hoja tenga datos
  private validateSheetHasData(worksheet: XLSX.WorkSheet, sheetName: string): string[] {
    const errors: string[] = [];
    
    try {
      const range = XLSX.utils.decode_range(worksheet['!ref'] || 'A1');
      const dataStartRow = this.HEADER_ROW + 2;
      
      let hasData = false;
      
      if (range.e.r >= dataStartRow) {
        const mainColumns = ['B', 'D', 'F', 'H'];
        
        for (let row = dataStartRow; row <= range.e.r; row++) {
          for (const col of mainColumns) {
            const cellAddress = `${col}${row}`;
            const cell = worksheet[cellAddress];
            
            if (cell && cell.v !== null && cell.v !== undefined && String(cell.v).trim() !== '') {
              hasData = true;
              break;
            }
          }
          if (hasData) break;
        }
      }
      
      if (!hasData) {
        errors.push(`La hoja "${sheetName}" no contiene datos. Se requiere al menos un registro con información.`);
      }
      
    } catch (error) {
      errors.push(`Error al validar datos en la hoja "${sheetName}": No se pudo verificar el contenido.`);
    }
    
    return errors;
  }

  // Método para validar los headers de una hoja específica
  private validateSheetHeaders(worksheet: XLSX.WorkSheet, sheetName: string): string[] {
    const errors: string[] = [];
     
    const expectedHeaders = this.TEMPLATE_STRUCTURE[sheetName];
    
    if (!expectedHeaders) {
      errors.push(`No se encontró la estructura esperada para la hoja: ${sheetName}`);
      return errors;
    }

    const range = XLSX.utils.decode_range(worksheet['!ref'] || 'A1');
    
    for (const [column, expectedHeader] of Object.entries(expectedHeaders)) {
      const cellAddress = `${column}${this.HEADER_ROW}`;
      const cell = worksheet[cellAddress];
      const actualHeader = cell ? String(cell.v).trim() : '';
      
      if (actualHeader !== expectedHeader) {
        errors.push(`Hoja "${sheetName}", Columna ${column}: Se esperaba "${expectedHeader}" pero se encontró "${actualHeader}"`);
      }
    }

    return errors;
  }



  // Método para validar el contenido del ZIP
  private async validateZipContent(file: File): Promise<{ isValid: boolean, errors: string[] }> {
    return new Promise((resolve) => {
      const reader = new FileReader();
      reader.onload = async (e: any) => {
        try {
          const zipData = new Uint8Array(e.target.result);
          const zip = new JSZip();
          const zipContent = await zip.loadAsync(zipData);
          
          const errors: string[] = [];
          const fileNames = Object.keys(zipContent.files);
          
          if (fileNames.length === 0) {
            errors.push('El archivo ZIP está vacío');
          }
          
          // Validar archivos y calcular tamaños
          let totalSize = 0;
          let fileCount = 0;
          
          for (const fileName of fileNames) {
            const zipEntry = zipContent.files[fileName];
            if (!zipEntry.dir) {
              fileCount++;
              
              // Para obtener el tamaño real, necesitamos leer el contenido
              try {
                const content = await zipEntry.async('uint8array');
                const fileSize = content.length;
                
                // Validar tamaño individual (10MB por archivo)
                if (fileSize > 1000 * 1024 * 1024) {
                  errors.push(`El archivo ${fileName} es demasiado grande (supera los 10MB)`);
                }
                
                totalSize += fileSize;
              } catch (fileError) {
                errors.push(`No se pudo leer el archivo ${fileName}`);
              }
            }
          }
          
          // Validar tamaño total descomprimido (100MB total)
          if (totalSize > 250 * 1024 * 1024) {
            errors.push('El contenido total del ZIP supera los 100MB');
          }
          
          // Validar número máximo de archivos (opcional)
          if (fileCount > 1000) {
            errors.push('El ZIP contiene demasiados archivos (máximo 1000)');
          }
          
          resolve({
            isValid: errors.length === 0,
            errors: errors
          });
          
        } catch (error) {
          resolve({
            isValid: false,
            errors: ['Error al leer el archivo ZIP']
          });
        }
      };
      reader.onerror = () => {
        resolve({
          isValid: false,
          errors: ['Error al leer el archivo']
        });
      };
      reader.readAsArrayBuffer(file);
    });
  }

  // Método para leer el contenido del ZIP
  private async readZipFile(file: File, fileId: string): Promise<void> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = async (e: any) => {
        try {
          const zipData = new Uint8Array(e.target.result);
          const zip = new JSZip();
          const zipContent = await zip.loadAsync(zipData);
          
          const files: ZipFileEntry[] = [];
          let totalSize = 0;
          let fileCount = 0;
          
          // Procesar cada entrada del ZIP
          for (const [relativePath, zipEntry] of Object.entries(zipContent.files)) {
            if (!zipEntry.dir) {
              // Es un archivo
              try {
                // Leer el contenido para obtener el tamaño real
                const content = await zipEntry.async('uint8array');
                const fileSize = content.length;
                totalSize += fileSize;
                fileCount++;
                
                // Determinar el tipo de archivo
                const extension = relativePath.split('.').pop()?.toLowerCase();
                let fileType = 'unknown';
                
                if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp'].includes(extension || '')) {
                  fileType = 'image';
                } else if (['pdf'].includes(extension || '')) {
                  fileType = 'pdf';
                } else if (['doc', 'docx'].includes(extension || '')) {
                  fileType = 'document';
                } else if (['txt', 'md', 'readme'].includes(extension || '')) {
                  fileType = 'text';
                } else if (['xlsx', 'xls', 'csv'].includes(extension || '')) {
                  fileType = 'excel';
                } else if (['ppt', 'pptx'].includes(extension || '')) {
                  fileType = 'presentation';
                } else if (['zip', 'rar', '7z'].includes(extension || '')) {
                  fileType = 'archive';
                } else if (['mp4', 'avi', 'mov', 'wmv'].includes(extension || '')) {
                  fileType = 'video';
                } else if (['mp3', 'wav', 'ogg'].includes(extension || '')) {
                  fileType = 'audio';
                }
                
                files.push({
                  name: relativePath,
                  size: fileSize,
                  isDirectory: false,
                  type: fileType
                });
                
              } catch (fileError) {
                console.warn(`No se pudo leer el archivo ${relativePath}:`, fileError);
                // Agregar el archivo con tamaño estimado
                files.push({
                  name: relativePath,
                  size: 0, // No pudimos obtener el tamaño
                  isDirectory: false,
                  type: 'unknown'
                });
              }
            } else {
              // Es un directorio
              files.push({
                name: relativePath,
                size: 0,
                isDirectory: true,
                type: 'folder'
              });
            }
          }
          
          this.zipData = {
            fileName: file.name,
            files: files.sort((a, b) => {
              // Ordenar: directorios primero, luego archivos por nombre
              if (a.isDirectory && !b.isDirectory) return -1;
              if (!a.isDirectory && b.isDirectory) return 1;
              return a.name.localeCompare(b.name);
            }),
            fileId: fileId,
            totalFiles: fileCount,
            totalSize: totalSize
          };
          
          resolve();
        } catch (error) {
          console.error('Error al leer el ZIP:', error);
          reject(error);
        }
      };
      reader.onerror = reject;
      reader.readAsArrayBuffer(file);
    });
  }

  async uploadExcelFile(fileData: File): Promise<void> {
    try {
      // Primero validar la estructura antes de subir
      const validationResult = await this.validateFileStructure(fileData);
      
      if (!validationResult.isValid) {
        this._resourcesService.openSnackBar(`Debe contener al menos un registro y cumplir con la estructura requerida`);
        this.isUploading = false;
        return;
      }

      const idUser = localStorage.getItem('idusuario');
      const formData = new FormData();

      formData.append('file', fileData);
      formData.append('id_user', idUser!);
      formData.append('linea', "1");
      formData.append('tipo_archivo', 'excel');

      const response = await lastValueFrom(this._gdelService.uploadTempFile(formData));

      if (response.error) {
        this._resourcesService.openSnackBar(response.msg);
      } else {
        this.uploadedFile = {
          id: response.response.idArchivo,
          name: fileData.name,
          size: this.formatBytes(fileData.size)
        };

        await this.readExcelFile(fileData, response.response.idArchivo);
        
        const newDocument: Document = {
          nombre_del_archivo: fileData.name,
          tamano_del_archivo: this.formatBytes(fileData.size),
          archivo_id: response.response.idArchivo,
          tipo_archivo: 'excel',
          fecha_carga: new Date().toLocaleString()
        };

        this.excelFile = newDocument;
        this.updateTableData();
        this._resourcesService.openSnackBar('Plantilla Excel válida y cargada exitosamente');
      }

      this.isUploading = false;
    } catch (error: any) {
      this.handleUploadError(error);
      this.isUploading = false;
    }
  }

  private async testndtry (er: any) {
    
  }
  
  // Método para validar la estructura del archivo antes de subirlo
  private async validateFileStructure(file: File): Promise<{ isValid: boolean, errors: string[] }> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = (e: any) => {
        try {
          const data = new Uint8Array(e.target.result);
          const workbook = XLSX.read(data, { type: 'array' });
          
          const validation = this.validateExcelTemplate(workbook);
          resolve(validation);
        } catch (error) {
          reject(error);
        }
      };
      reader.onerror = reject;
      reader.readAsArrayBuffer(file);
    });
  }

  private async readExcelFile(file: File, fileId: any): Promise<void> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = (e: any) => {
        try {
          const data = new Uint8Array(e.target.result);
          const workbook = XLSX.read(data, { type: 'array' });
          
          const sheetNames = workbook.SheetNames;
          const sheetsData: any = {};
          
          sheetNames.forEach(sheetName => {
            const worksheet = workbook.Sheets[sheetName];
            sheetsData[sheetName] = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
          });

          this.excelData = {
            fileName: file.name,
            sheets: sheetsData,
            sheetNames: sheetNames,
            fileId: fileId
          };

          resolve();
        } catch (error) {
          reject(error);
        }
      };
      reader.onerror = reject;
      reader.readAsArrayBuffer(file);
    });
  }


  formatBytes(bytes: number, decimals = 2): string {
    if (bytes === 0) return '0 Bytes';

    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

    const i = Math.floor(Math.log(bytes) / Math.log(k));

    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
  }

  private updateTableData(): void {
    const files: Document[] = [];
    if (this.excelFile) files.push(this.excelFile);
    if (this.zipFile) files.push(this.zipFile);
    this.dataSource.data = files;
  }

  private loadFiles(): void {
    this.excelFile = null;
    this.zipFile = null;
    this.updateTableData();
  }

  private handleUploadError(error: any): void {
    if (error.error == undefined) {
      this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
    } else if (error.error.msg == undefined) {
      this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
    } else {
      this._resourcesService.openSnackBar(error.error.msg);
    }
  }

  // Método para abrir previsualización del Excel
  previewExcelFile(): void {
    if (!this.excelData) {
      this._resourcesService.openSnackBar('No hay datos del archivo Excel para mostrar');
      return;
    }

    const dialogRef = this._matDialog.open(PreviewDocumentsComponent, {
      width: '1800px',
      height: '900px',
      maxWidth: '1800px',
      data: this.excelData,
      disableClose: true
    });

    dialogRef.afterClosed().subscribe(result => {
      if (result) {
        console.log('Preview cerrado:', result);
      }
    });
  }



  // Métodos para eliminar archivos específicos
  removeExcelFile(): void {
    this.deleteTempFile('excel');
  }

  removeZipFile(): void {
    this.deleteTempFile('zip');
  }

  // Getters para verificar si hay archivos cargados
  get hasExcelFile(): boolean {
    return this.excelFile !== null;
  }

  get hasZipFile(): boolean {
    return this.zipFile !== null;
  }

  get hasAnyFile(): boolean {
    return this.hasExcelFile || this.hasZipFile;
  }

  // Getter para obtener información del ZIP
  get zipInfo(): string {
    if (!this.zipData) return '';
    return `${this.zipData.totalFiles} archivos (${this.formatBytes(this.zipData.totalSize)})`;
  }

 







private async processValidatedFiles(validationResult: any): Promise<void> {
  if (!validationResult.foundFiles || validationResult.foundFiles.length === 0) {
    this._resourcesService.openSnackBar('No hay archivos validados para procesar');
    return;
  }

  try {
    this._resourcesService.openSnackBar(`Procesando ${validationResult.foundFiles.length} archivos validados...`);
     
    console.log('Archivos encontrados para procesar:', validationResult.foundFiles);
    console.log('Detalles de validación:', validationResult.validationDetails);
    
  await this.processIndividualFiles(validationResult.foundFiles);
    
  } catch (error) {
    console.error('Error al procesar archivos validados:', error);
    this._resourcesService.openSnackBar('Error al procesar los archivos validados');
  }
}


private async processIndividualFiles(foundFiles: string[]): Promise<void> {
  for (const fileName of foundFiles) {
    try {
      console.log(`Procesando archivo: ${fileName}`);
      
      
    } catch (error) {
      console.error(`Error al procesar archivo ${fileName}:`, error);
    }
  }
}



// Método para mostrar resumen de archivos esperados (opcional):

public getExpectedFilesFromExcel(): string[] {
  if (!this.excelData) return [];
  
  const expectedFiles: string[] = [];
  const TEMPLATE_COLUMNS = ['H', 'J', 'L', 'N', 'P', 'R', 'T', 'V'];
  const DATA_START_ROW = 9;
  
  try {
    const sheet = this.excelData.sheets['CARGA DE DOCUMENTOS'];
    if (!sheet) return [];

    for (let rowIndex = DATA_START_ROW - 1; rowIndex < sheet.length; rowIndex++) {
      const row = sheet[rowIndex];
      if (!row) continue;

      TEMPLATE_COLUMNS.forEach(column => {
        const columnIndex = this.getColumnIndex(column);
        const cellValue = row[columnIndex];
        
        if (cellValue && typeof cellValue === 'string' && cellValue.trim() !== '') {
          const fileName = cellValue.trim();
          if (this.hasValidFileExtension(fileName)) {
            expectedFiles.push(fileName);
          }
        }
      });
    }
  } catch (error) {
    console.error('Error al extraer archivos esperados:', error);
  }

  return expectedFiles;
}

private getColumnIndex(column: string): number {
  const columnMap: { [key: string]: number } = {
    'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7,
    'I': 8, 'J': 9, 'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14, 'P': 15,
    'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'U': 20, 'V': 21, 'W': 22, 'X': 23
  };
  return columnMap[column] || 0;
}



// Método para extraer nombres de documentos del Excel
public extractDocumentNamesFromExcel(): ExcelDocumentEntry[] {
  if (!this.excelData || !this.excelData.sheets['CARGA DE DOCUMENTOS']) {
    return [];
  }

  const documentEntries: ExcelDocumentEntry[] = [];
  const sheet = this.excelData.sheets['CARGA DE DOCUMENTOS'];
  
  // Definir las columnas de documentos y sus categorías
  const DOCUMENT_COLUMNS = [
    { letter: 'H', index: 7, category: 'FICHA DE SEGURIDAD DE PRODUCTOS QUÍMICOS' },
    { letter: 'J', index: 9, category: 'FICHA TÉCNICA' },
    { letter: 'L', index: 11, category: 'FOTOGRAFÍAS - DIAGRAMAS' },
    { letter: 'N', index: 13, category: 'DATOS DEL PROVEEDOR' },
    { letter: 'P', index: 15, category: 'MANUALES DE OPERACIÓN' },
    { letter: 'R', index: 17, category: 'MANUALES DE MANTENIMIENTO PREVENTIVO' },
    { letter: 'T', index: 19, category: 'MANUALES DE MANTENIMIENTO CORRECTIVO' },
    { letter: 'V', index: 21, category: 'DOCUMENTOS ADICIONALES' }
  ];

  const DATA_START_ROW = 9; // Fila 9 en Excel (índice 8 en array)

  try {
    // Recorrer desde la fila 9 hacia abajo
    for (let rowIndex = DATA_START_ROW - 1; rowIndex < sheet.length; rowIndex++) {
      const row = sheet[rowIndex];
      if (!row) continue;

      // Verificar si la fila tiene datos principales (columnas A, C, E)
      const hasMainData = row[1] || row[3] || row[5]; 
      if (!hasMainData) continue; // Saltar filas vacías

      // Revisar cada columna de documentos
      DOCUMENT_COLUMNS.forEach(column => {
        const cellValue = row[column.index];
        
        if (cellValue && typeof cellValue === 'string' && cellValue.trim() !== '') {
          const documentName = cellValue.trim();
          
          // Validar que tenga una extensión de archivo válida
          if (this.hasValidFileExtension(documentName)) {
            documentEntries.push({
              rowIndex: rowIndex + 1, // +1 para mostrar número de fila real
              columnLetter: column.letter,
              columnIndex: column.index,
              documentName: documentName,
              category: column.category
            });
          }
        }
      });
    }
  } catch (error) {
    console.error('Error al extraer nombres de documentos del Excel:', error);
  }

  return documentEntries;
}

// Método para validar documentos entre Excel y ZIP
public validateDocumentsInZip(): DocumentValidationResult {
  const expectedDocuments = this.extractDocumentNamesFromExcel();
  const expectedFileNames = expectedDocuments.map(doc => doc.documentName.toLowerCase());
  
  if (!this.zipData || !this.zipData.files) {
    return {
      isValid: false,
      foundFiles: [],
      missingFiles: expectedFileNames,
      extraFiles: [],
      validationDetails: {
        expectedCount: expectedFileNames.length,
        foundCount: 0,
        matchedCount: 0
      }
    };
  }

  // Obtener nombres de archivos del ZIP (solo archivos, no directorios)
  const zipFileNames = this.zipData.files
    .filter(file => !file.isDirectory)
    .map(file => {
      // Obtener solo el nombre del archivo sin la ruta
      const fileName = file.name.split('/').pop() || file.name;
      return fileName.toLowerCase();
    });

  // Encontrar archivos que coinciden
  const foundFiles: string[] = [];
  const missingFiles: string[] = [];

  expectedFileNames.forEach(expectedFile => {
    const found = zipFileNames.find(zipFile => {
      // Comparación exacta de nombres
      return zipFile === expectedFile;
    });

    if (found) {
      foundFiles.push(expectedFile);
    } else {
      missingFiles.push(expectedFile);
    }
  });

  // Encontrar archivos extra (en ZIP pero no en Excel)
  const extraFiles = zipFileNames.filter(zipFile => 
    !expectedFileNames.includes(zipFile)
  );

  const isValid = missingFiles.length === 0 && foundFiles.length > 0;

  return {
    isValid,
    foundFiles,
    missingFiles,
    extraFiles,
    validationDetails: {
      expectedCount: expectedFileNames.length,
      foundCount: foundFiles.length,
      matchedCount: foundFiles.length
    }
  };
}



// Método para procesar archivos en lotes
private async processBatchFiles(validationResult: DocumentValidationResult): Promise<void> {
  const idUser = localStorage.getItem('idusuario');
  
  if (!idUser || !this.uploadedFile) {
    throw new Error('No se encontró información del usuario o archivo');
  }

  // Procesar archivos en lotes para evitar sobrecargar el servidor
  const batchSize = 3; // Procesar de 3 en 3
  const foundFiles = validationResult.foundFiles;
  
  for (let i = 0; i < foundFiles.length; i += batchSize) {
    const batch = foundFiles.slice(i, i + batchSize);
    
    // Procesar lote actual
    await Promise.all(batch.map(async (fileName) => {
      try {
        // Primero saveTempFile
        await this.saveTempFileForDocument(fileName, idUser);
        
        // Luego saveFinalFile
        await this.saveFinalFileForDocument(fileName, idUser);
        
        console.log(`Documento procesado exitosamente: ${fileName}`);
      } catch (error) {
        console.error(`Error al procesar documento ${fileName}:`, error);
        throw error; // Re-lanzar error para detener el proceso
      }
    }));
    
    // Pequeña pausa entre lotes
    if (i + batchSize < foundFiles.length) {
      await new Promise(resolve => setTimeout(resolve, 500));
    }
  }
}

// Método para saveTempFile de un documento específico
private async saveTempFileForDocument(fileName: string, idUser: string): Promise<any> {
  const formData = new FormData();
  
  formData.append('id_user', idUser);
  formData.append('file_name', fileName);
  formData.append('zip_file_id', this.uploadedFile!.id);
  formData.append('linea', '1');
  formData.append('tipo_archivo','');

  const response = await lastValueFrom(this._gdelService.uploadTempFile(formData));
  
  if (response.error) {
    throw new Error(`Error en saveTempFile para ${fileName}: ${response.msg}`);
  }
  
  return response;
}

// Método para saveFinalFile de un documento específico
private async saveFinalFileForDocument(fileName: string, idUser: string): Promise<any> {
  const formData = new FormData();
  
  formData.append('id_user', idUser);
  formData.append('file_name', fileName);
  formData.append('zip_file_id', this.uploadedFile!.id);
  formData.append('linea', '1');
  formData.append('module', 'ADSI');
  formData.append('clasification', 'LA');
  formData.append('has_order', 'N');

  const response = await lastValueFrom(this._gdelService.saveFinalFile(formData));
  
  if (response.error) {
    throw new Error(`Error en saveFinalFile para ${fileName}: ${response.msg}`);
  }
  
  return response;
}

// Método actualizado para validar extensiones de archivo
private hasValidFileExtension(fileName: string): boolean {
  if (!fileName || !fileName.includes('.')) return false;
  
  const validExtensions = [
    '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx',
    '.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.svg', '.webp',
    '.txt', '.rtf', '.csv', '.xml', '.json',
    '.zip', '.rar', '.7z',
    '.mp4', '.avi', '.mov', '.wmv', '.flv', '.mkv',
    '.mp3', '.wav', '.ogg', '.aac', '.flac'
  ];
  
  const extension = fileName.toLowerCase().substring(fileName.lastIndexOf('.'));
  return validExtensions.includes(extension);
}

// Método para obtener estadísticas de validación
public getValidationSummary(): string {
  if (!this.canValidateFiles) return 'Cargue ambos archivos para ver el resumen';
  
  const validation = this.validateDocumentsInZip();
  const { expectedCount, foundCount, matchedCount } = validation.validationDetails;
  
  if (expectedCount === 0) return 'No se encontraron documentos en el Excel';
  
  return `${matchedCount}/${expectedCount} documentos encontrados en el ZIP`;
}

// Getter actualizado para verificar si se puede validar
get canValidateFiles(): boolean {
  return this.hasExcelFile && this.hasZipFile && 
         this.excelData && this.zipData && 
         this.extractDocumentNamesFromExcel().length > 0;
}





// Método para procesar archivos en lotes desde preview
private async processBatchFilesFromPreview(foundFiles: string[]): Promise<void> {
  const idUser = localStorage.getItem('idusuario');
  
  if (!idUser || !this.uploadedFile) {
    throw new Error('No se encontró información del usuario o archivo');
  }

  // Procesar archivos en lotes para evitar sobrecargar el servidor
  const batchSize = 3; // Procesar de 3 en 3
  
  for (let i = 0; i < foundFiles.length; i += batchSize) {
    const batch = foundFiles.slice(i, i + batchSize);
    
    // Procesar lote actual
    await Promise.all(batch.map(async (fileName) => {
      try {
        console.log(`Procesando documento: ${fileName}`);
        
        // Primero saveTempFile
        const tempResult = await this.saveTempFileForDocument(fileName, idUser);
        console.log(`saveTempFile exitoso para ${fileName}:`, tempResult);
        
        // Luego saveFinalFile
        const finalResult = await this.saveFinalFileForDocument(fileName, idUser);
        console.log(`saveFinalFile exitoso para ${fileName}:`, finalResult);
        
      } catch (error) {
        console.error(`Error al procesar documento ${fileName}:`, error);
        throw error; // Re-lanzar error para detener el proceso
      }
    }));
    
    // Pequeña pausa entre lotes
    if (i + batchSize < foundFiles.length) {
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
  }
}





// Método alternativo para validar y procesar directamente (sin preview)
public async validateAndProcessDocuments(): Promise<void> {
  if (!this.canValidateFiles) {
    this._resourcesService.openSnackBar('Debe cargar tanto el archivo Excel como el ZIP antes de validar');
    return;
  }

  try {
    this.isLoading = true;
    
    // Extraer documentos esperados del Excel
    const expectedDocuments = this.extractDocumentNamesFromExcel();
    
    if (expectedDocuments.length === 0) {
      this._resourcesService.openSnackBar('No se encontraron documentos en el Excel para validar');
      return;
    }

    // Validar documentos
    const validationResult = this.validateDocumentsInZip();
    
    if (!validationResult.isValid || validationResult.foundFiles.length === 0) {
      const missingCount = validationResult.missingFiles.length;
      const message = missingCount > 0 
        ? `Faltan ${missingCount} documentos en el ZIP. Documentos faltantes: ${validationResult.missingFiles.slice(0, 3).join(', ')}${missingCount > 3 ? '...' : ''}`
        : 'No se encontraron documentos válidos para procesar';
      
      this._resourcesService.openSnackBar(message);
      return;
    }

    // Mostrar resultado de validación
    const foundCount = validationResult.foundFiles.length;
    const expectedCount = validationResult.validationDetails.expectedCount;
    
    this._resourcesService.openSnackBar(
      `Validación exitosa: ${foundCount}/${expectedCount} documentos encontrados. Procesando...`
    );

    // Procesar cada archivo encontrado
    await this.processBatchFilesFromPreview(validationResult.foundFiles);

    this._resourcesService.openSnackBar('Validación y procesamiento completado exitosamente');
    this.dialogRef.close({ 
      success: true, 
      validationResult,
      processedCount: foundCount 
    });

  } catch (error: any) {
    console.error('Error en validación y procesamiento:', error);
    this._resourcesService.openSnackBar('Error: ' + (error.message || 'Error desconocido'));
  } finally {
    this.isLoading = false;
  }
}

// Método para mostrar resumen detallado de validación
public showValidationSummary(): void {
  if (!this.canValidateFiles) {
    this._resourcesService.openSnackBar('Debe cargar tanto el archivo Excel como el ZIP antes de validar');
    return;
  }

  const expectedDocuments = this.extractDocumentNamesFromExcel();
  const validationResult = this.validateDocumentsInZip();

  console.log('=== RESUMEN DE VALIDACIÓN ===');
  console.log('Documentos esperados del Excel:', expectedDocuments);
  console.log('Resultado de validación:', validationResult);
  console.log('Archivos encontrados:', validationResult.foundFiles);
  console.log('Archivos faltantes:', validationResult.missingFiles);
  console.log('Archivos extra en ZIP:', validationResult.extraFiles);

  const summary = `
     RESUMEN DE VALIDACIÓN:
    • Documentos esperados: ${validationResult.validationDetails.expectedCount}
    • Documentos encontrados: ${validationResult.validationDetails.foundCount}
    • Estado: ${validationResult.isValid ? ' VÁLIDO' : ' INCOMPLETO'}
    ${validationResult.missingFiles.length > 0 ? `\n• Faltan: ${validationResult.missingFiles.join(', ')}` : ''}
  `;

  this._resourcesService.openSnackBar(summary);
}

// Getter para verificar el estado de validación en tiempo real
get validationStatus(): string {
  if (!this.canValidateFiles) return 'Sin datos para validar';
  
  const expectedDocuments = this.extractDocumentNamesFromExcel();
  if (expectedDocuments.length === 0) return 'Sin documentos en Excel';
  
  const validationResult = this.validateDocumentsInZip();
  const { expectedCount, foundCount } = validationResult.validationDetails;
  
  return `${foundCount}/${expectedCount} documentos encontrados`;
}

// Método para limpiar datos de validación
public clearValidationData(): void {
  // Este método se puede usar si necesitas resetear el estado de validación
  console.log('Limpiando datos de validación...');
}



// Método para exportar datos de validación 
public exportValidationReport(): void {
  if (!this.canValidateFiles) return;

  const expectedDocuments = this.extractDocumentNamesFromExcel();
  const validationResult = this.validateDocumentsInZip();

  const report = {
    timestamp: new Date().toISOString(),
    excelFile: this.excelFile?.nombre_del_archivo,
    zipFile: this.zipFile?.nombre_del_archivo,
    expectedDocuments: expectedDocuments,
    validation: validationResult,
    summary: {
      expected: validationResult.validationDetails.expectedCount,
      found: validationResult.validationDetails.foundCount,
      missing: validationResult.missingFiles.length,
      extra: validationResult.extraFiles.length,
      isComplete: validationResult.isValid
    }
  };

    const blob = new Blob([JSON.stringify(report, null, 2)], { type: 'application/json' });
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `validation-report-${Date.now()}.json`;
  a.click();
  window.URL.revokeObjectURL(url);
}



private async extractFileFromZip(fileName: string): Promise<File | null> {
  if (!this.zipData) return null;

  return new Promise((resolve) => {
    const reader = new FileReader();

    reader.onload = async (e: any) => {
      try {
        const zipData = new Uint8Array(e.target.result);
        const zip = new JSZip();
        const zipContent = await zip.loadAsync(zipData);
        
        // Buscar el archivo específico en el ZIP
        const targetFile = Object.entries(zipContent.files).find(([path, entry]) => {
          const entryFileName = path.split('/').pop()?.toLowerCase();
          return entryFileName === fileName.toLowerCase() && !entry.dir;
        });

        if (targetFile) {
          const [filePath, zipEntry] = targetFile;
          const content = await zipEntry.async('blob');
          const file = new File([content], fileName, { 
            type: this.getMimeType(fileName) 
          });
          resolve(file);
        } else {
          resolve(null);
        }
      } catch (error) {
        console.error('Error al extraer archivo del ZIP:', error);
        resolve(null);
      }
    };
    reader.onerror = () => resolve(null);
    
    // Aquí necesitas acceso al archivo ZIP original
    // Debes guardar una referencia al File original del ZIP
    if (this.originalZipFile) {
      reader.readAsArrayBuffer(this.originalZipFile);
    } else {
      resolve(null);
    }
  });
}

// Método auxiliar para obtener MIME type
private getMimeType(fileName: string): string {
  const extension = fileName.toLowerCase().split('.').pop();
  const mimeTypes: { [key: string]: string } = {
    'pdf': 'application/pdf',
    'doc': 'application/msword',
    'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    'xls': 'application/vnd.ms-excel',
    'jpg': 'image/jpeg',
    'jpeg': 'image/jpeg',
    'png': 'image/png',
    'gif': 'image/gif',
    'bmp': 'image/bmp',
    'svg': 'image/svg+xml',
    'txt': 'text/plain'
  };
  return mimeTypes[extension || ''] || 'application/octet-stream';
}

// Método corregido para subir archivo individual desde ZIP
private async uploadTempFileFromZip(fileName: string): Promise<string | null> {
  try {
    // Extraer el archivo individual del ZIP
    const individualFile = await this.extractFileFromZip(fileName);
    
    if (!individualFile) {
      throw new Error(`No se pudo extraer el archivo ${fileName} del ZIP`);
    }

    const idUser = localStorage.getItem('idusuario');
    const formData = new FormData();

    formData.append('file', individualFile);
    formData.append('id_user', idUser!);
    formData.append('linea', '1');
    
    // Determinar tipo de archivo basado en extensión
    const extension = fileName.toLowerCase().split('.').pop();
    let tipoArchivo = 'documento';
    
    if (['pdf'].includes(extension || '')) {
      tipoArchivo = 'pdf';
    } else if (['doc', 'docx'].includes(extension || '')) {
      tipoArchivo = 'docx';
    } else if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg'].includes(extension || '')) {
      tipoArchivo = 'img';
    } else if (['xlsx', 'xls'].includes(extension || '')) {
      tipoArchivo = 'excel';
    }
    
    formData.append('tipo_archivo', tipoArchivo);

    const response = await lastValueFrom(this._gdelService.uploadTempFile(formData));

    if (response.error) {
      throw new Error(response.msg || `Error al subir ${fileName}`);
    }

    console.log(` uploadTempFile exitoso para ${fileName}:`, response.response.idArchivo);
    return response.response.idArchivo;

  } catch (error: any) {
    console.error(` Error en uploadTempFile para ${fileName}:`, error);
    throw error;
  }
}

// Método corregido para guardar archivo final individual
private async saveFinalFileIndividual(fileId: string, fileName: string): Promise<void> {
  try {
    const idUser = localStorage.getItem('idusuario');
    const formData = new FormData();

    // Parámetros obligatorios
    formData.append('id_user', idUser!);
    formData.append('id_file', fileId);
    formData.append('linea', '1');
    
    // Parámetros específicos para equipamiento
    formData.append('module', 'ADSI');
    formData.append('clasification', 'LA');
    formData.append('has_order', 'N');

    const response = await lastValueFrom(this._gdelService.saveFinalFile(formData));

    if (response.error) {
      throw new Error(response.msg || `Error al guardar ${fileName}`);
    }

    console.log(` saveFinalFile exitoso para ${fileName}:`, response);

  } catch (error: any) {
    console.error(` Error en saveFinalFile para ${fileName}:`, error);
    throw error;
  }
}

// Método principal corregido para procesar documentos validados
public async processValidatedDocuments(): Promise<void> {
  if (!this.canValidateFiles) {
    this._resourcesService.openSnackBar('Debe cargar tanto el archivo Excel como el ZIP antes de validar');
    return;
  }

  try {
    this.isLoading = true;
    
    // Validar documentos
    const validationResult = this.validateDocumentsInZip();
    
    if (!validationResult.isValid || validationResult.foundFiles.length === 0) {
      const missingCount = validationResult.missingFiles.length;
      const message = missingCount > 0 
        ? `Faltan ${missingCount} documentos en el ZIP: ${validationResult.missingFiles.slice(0, 3).join(', ')}${missingCount > 3 ? '...' : ''}`
        : 'No se encontraron documentos válidos para procesar';
      
      this._resourcesService.openSnackBar(message);
      return;
    }

    const foundCount = validationResult.foundFiles.length;
    this._resourcesService.openSnackBar(
      `Validación exitosa: ${foundCount} documentos encontrados. Procesando...`
    );

    // Procesar cada documento individualmente
    let processedCount = 0;
    let errors: string[] = [];

    for (const fileName of validationResult.foundFiles) {
      try {
        console.log(` Procesando documento: ${fileName}`);
        

        const fileId = await this.uploadTempFileFromZip(fileName);
        
        if (!fileId) {
          throw new Error(`No se obtuvo ID del archivo para ${fileName}`);
        }


        await this.saveFinalFileIndividual(fileId, fileName);
        
        processedCount++;
        console.log(` Documento procesado exitosamente: ${fileName} (${processedCount}/${foundCount})`);
        
        // Actualizar progreso en la UI
        this._resourcesService.openSnackBar(
          `Procesado: ${fileName} (${processedCount}/${foundCount})`
        );

        // Pausa pequeña entre archivos para no sobrecargar el servidor
        await new Promise(resolve => setTimeout(resolve, 500));

      } catch (error: any) {
        const errorMsg = `Error procesando ${fileName}: ${error.message}`;
        console.error('', errorMsg);
        errors.push(errorMsg);
        
        // Opcional: continuar con el siguiente archivo o detener todo
        // Para continuar, simplemente log el error y sigue
        // Para detener, descomenta la siguiente línea:
        // throw error;
      }
    }

    // Mostrar resultado final
    if (processedCount > 0) {
      const successMsg = ` ${processedCount} documentos procesados exitosamente`;
      this._resourcesService.openSnackBar(successMsg);
      
      if (errors.length > 0) {
        console.warn(' Errores durante el procesamiento:', errors);
        this._resourcesService.openSnackBar(`Procesados: ${processedCount}, Errores: ${errors.length}`);
      }
      
      // Cerrar diálogo con éxito
      this.dialogRef.close({ 
        success: true, 
        validationResult,
        processedCount,
        errors: errors.length > 0 ? errors : undefined
      });
    } else {
      throw new Error('No se pudo procesar ningún documento');
    }

  } catch (error: any) {
    console.error('Error general en procesamiento:', error);
    this._resourcesService.openSnackBar('Error: ' + (error.message || 'Error desconocido'));
  } finally {
    this.isLoading = false;
  }
}

//método uploadZipFile para guardar referencia al archivo original

async uploadZipFile(fileData: File): Promise<void> {
  try {
    // Guardar referencia al archivo original para extracciones posteriores
    this.originalZipFile = fileData;
    
    // ... resto del código existente del método uploadZipFile ...
    
    // Validar contenido del ZIP
    const zipValidation = await this.validateZipContent(fileData);
    
    if (!zipValidation.isValid) {
      this._resourcesService.openSnackBar(`Error en el archivo ZIP: ${zipValidation.errors.join(', ')}`);
      this.isUploading = false;
      return;
    }

    

    this.uploadedFile = {
      id: 'temp-zip-' + Date.now(), // ID temporal
      name: fileData.name,
      size: this.formatBytes(fileData.size)
    };

    // Leer el contenido del ZIP para visualización
    await this.readZipFile(fileData, this.uploadedFile.id);
    
    const newDocument: Document = {
      nombre_del_archivo: fileData.name,
      tamano_del_archivo: this.formatBytes(fileData.size),
      archivo_id: this.uploadedFile.id,
      tipo_archivo: 'zip',
      fecha_carga: new Date().toLocaleString()
    };

    this.zipFile = newDocument;
    this.updateTableData();
    this._resourcesService.openSnackBar('Archivo ZIP cargado y listo para validación');

    this.isUploading = false;
    
  } catch (error: any) {
    this.handleUploadError(error);
    this.isUploading = false;
  }
}

//Actualizar el método de limpieza
async deleteTempFile(fileType: 'excel' | 'zip'): Promise<void> {
  try {
    if (fileType === 'zip') {
      // Para ZIP, solo limpiar referencias locales
      this.originalZipFile = null;
      this.zipFile = null;
      this.zipData = null;
      this.uploadedFile = null;
    } else if (fileType === 'excel' && this.uploadedFile) {
      // Para Excel, eliminar del servidor si fue subido
      const idUser = localStorage.getItem('idusuario');
      const formData = new FormData();

      formData.append('id_user', idUser!);
      formData.append('id_file', this.uploadedFile.id);
      formData.append('linea', '1');

      await lastValueFrom(this._gdelService.deleteTempFile(formData));
      
      this.excelFile = null;
      this.excelData = null;
      this.uploadedFile = null;
    }
    
    this.currentFileType = null;
    this.updateTableData();
    this._resourcesService.openSnackBar('Archivo eliminado exitosamente');
    
  } catch (error: any) {
    this.handleUploadError(error);
  }
}

// Nuevo método para subir archivos individuales del ZIP a uploadTempFile
async uploadDocumentFromZip(fileName: string, zipFileContent: Uint8Array): Promise<string | null> {
  try {
    const idUser = localStorage.getItem('idusuario');
    
    // Crear un File object desde el contenido del ZIP
    const file = new File([zipFileContent], fileName, { 
      type: this.getMimeType(fileName) 
    });

    const formData = new FormData();
    formData.append('file', file);
    formData.append('id_user', idUser!);
    formData.append('linea', '1');
    
    // Determinar tipo de archivo basado en extensión
    const extension = fileName.toLowerCase().split('.').pop();
    let tipoArchivo = 'documento';
    
    if (['pdf'].includes(extension || '')) {
      tipoArchivo = 'pdf';
    } else if (['doc', 'docx'].includes(extension || '')) {
      tipoArchivo = 'docx';
    } else if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg'].includes(extension || '')) {
      tipoArchivo = 'img';
    } else if (['xlsx', 'xls'].includes(extension || '')) {
      tipoArchivo = 'excel';
    }
    
    formData.append('tipo_archivo', tipoArchivo);

    const response = await lastValueFrom(this._gdelService.uploadTempFile(formData));

    if (response.error) {
      throw new Error(response.msg || `Error al subir ${fileName}`);
    }

    console.log(` Documento subido a temp: ${fileName} - ID: ${response.response.idArchivo}`);
    return response.response.idArchivo;

  } catch (error: any) {
    console.error(` Error subiendo ${fileName}:`, error);
    throw error;
  }
}

// 2. Método para procesar documentos validados desde el preview
private async processValidatedDocumentsFromPreview(validationResult: any): Promise<void> {
  if (!validationResult.foundFiles || validationResult.foundFiles.length === 0) {
    this._resourcesService.openSnackBar('No hay archivos validados para procesar');
    return;
  }

  try {
    this.isLoading = true;
    
    const foundCount = validationResult.foundFiles.length;
    this._resourcesService.openSnackBar(`Procesando ${foundCount} documentos...`);

    // Procesar cada archivo encontrado
    const processedDocuments: ProcessedDocument[] = [];
    
    for (const fileName of validationResult.foundFiles) {
      try {
        console.log(` Procesando: ${fileName}`);
        
        // Extraer contenido del archivo desde el ZIP
        const fileContent = await this.extractFileContentFromZip(fileName);
        
        if (!fileContent) {
          throw new Error(`No se pudo extraer el contenido de ${fileName}`);
        }

        // Subir a uploadTempFile
        const fileId = await this.uploadDocumentFromZip(fileName, fileContent);
        
        if (!fileId) {
          throw new Error(`No se obtuvo ID para ${fileName}`);
        }

        // Crear registro del documento procesado
        const processedDoc: ProcessedDocument = {
          nombre_del_archivo: fileName,
          tamano_del_archivo: this.formatBytes(fileContent.length),
          archivo_id: fileId,
          tipo_archivo: this.getFileTypeFromExtension(fileName),
          fecha_carga: new Date().toLocaleString(),
          estado: 'temp_uploaded'
        };

        processedDocuments.push(processedDoc);
        
        console.log(` Procesado exitosamente: ${fileName}`);
        
        // Pausa pequeña entre archivos
        await new Promise(resolve => setTimeout(resolve, 300));

      } catch (error: any) {
        console.error(` Error procesando ${fileName}:`, error);
        
        // Agregar documento con error
        processedDocuments.push({
          nombre_del_archivo: fileName,
          tamano_del_archivo: '0 B',
          archivo_id: '',
          tipo_archivo: 'error',
          fecha_carga: new Date().toLocaleString(),
          estado: 'error',
          error_message: error.message
        });
      }
    }

    // Actualizar la lista de documentos procesados
    this.processedDocuments = processedDocuments;
    this.updateAllTableData();

    const successCount = processedDocuments.filter(doc => doc.estado === 'temp_uploaded').length;
    const errorCount = processedDocuments.filter(doc => doc.estado === 'error').length;

    if (successCount > 0) {
      this._resourcesService.openSnackBar(
        ` ${successCount} documentos procesados${errorCount > 0 ? `, ${errorCount} errores` : ''}`
      );
    } else {
      throw new Error('No se pudo procesar ningún documento');
    }

  } catch (error: any) {
    console.error('Error en procesamiento:', error);
    this._resourcesService.openSnackBar('Error: ' + (error.message || 'Error desconocido'));
  } finally {
    this.isLoading = false;
  }
}

//Método para extraer contenido de archivo desde ZIP
private async extractFileContentFromZip(fileName: string): Promise<Uint8Array | null> {
  if (!this.originalZipFile) {
    console.error('No hay archivo ZIP original disponible');
    return null;
  }

  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = async (e: any) => {
      try {
        const zipData = new Uint8Array(e.target.result);
        const zip = new JSZip();
        const zipContent = await zip.loadAsync(zipData);
        
        // Buscar el archivo específico en el ZIP
        const targetFile = Object.entries(zipContent.files).find(([path, entry]) => {
          const entryFileName = path.split('/').pop()?.toLowerCase();
          return entryFileName === fileName.toLowerCase() && !entry.dir;
        });

        if (targetFile) {
          const [filePath, zipEntry] = targetFile;
          const content = await zipEntry.async('uint8array');
          resolve(content);
        } else {
          console.error(`Archivo ${fileName} no encontrado en ZIP`);
          resolve(null);
        }
      } catch (error) {
        console.error('Error extrayendo archivo del ZIP:', error);
        resolve(null);
      }
    };
    reader.onerror = () => resolve(null);
    reader.readAsArrayBuffer(this.originalZipFile!);
  });
}

//Método auxiliar para obtener tipo de archivo
private getFileTypeFromExtension(fileName: string): string {
  const extension = fileName.toLowerCase().split('.').pop();
  
  const typeMap: { [key: string]: string } = {
    'pdf': 'pdf',
    'doc': 'docx',
    'docx': 'docx',
    'xlsx': 'excel',
    'xls': 'excel',
    'jpg': 'imagen',
    'jpeg': 'imagen',
    'png': 'imagen',
    'gif': 'imagen',
    'bmp': 'imagen',
    'svg': 'imagen',
    'txt': 'texto',
    'zip': 'archivo',
    'rar': 'archivo'
  };
  
  return typeMap[extension || ''] || 'documento';
}

// Método actualizado para manejar el resultado del preview
previewZipFile(): void {
  if (!this.zipData) {
    this._resourcesService.openSnackBar('No hay datos del archivo ZIP para mostrar');
    return;
  }

  const dialogRef = this._matDialog.open(PreviewFileContentComponent, {
    width: '1200px',
    height: '800px',
    maxWidth: '1200px',
    data: {
      fileName: this.zipData.fileName,
      fileType: 'zip',
      zipContent: this.zipData,
      fileId: this.zipData.fileId,
      excelData: this.excelData // Pasar datos del Excel para validación
    },
    disableClose: true
  });

  dialogRef.afterClosed().subscribe(result => {
    if (result && result.action === 'validate' && result.validationResult) {
      console.log('Validación completada:', result);
      
      // Procesar documentos validados
      this.processValidatedDocumentsFromPreview(result.validationResult);
    }
  });
}


// Método para actualizar todas las tablas
private updateAllTableData(): void {
  // Esto se actualizará según el nuevo HTML
}

// Getters para validar estado
get hasRequiredFiles(): boolean {
  return this.hasExcelFile && this.hasZipFile;
}

get canProcessDocuments(): boolean {
  return this.hasRequiredFiles && this.processedDocuments.length > 0;
}

get requirementsMessage(): string {
  if (!this.hasExcelFile && !this.hasZipFile) {
    return 'Se necesita cargar el archivo Excel y el ZIP';
  } else if (!this.hasExcelFile) {
    return 'Se necesita cargar el archivo Excel';
  } else if (!this.hasZipFile) {
    return 'Se necesita cargar el archivo ZIP';
  }
  return '';
}

async saveFinalFile(): Promise<void> {
  const documentsToSave = this.processedDocuments.filter(doc => 
    doc.estado === 'temp_uploaded' && doc.archivo_id
  );

  if (documentsToSave.length === 0) {
    this._resourcesService.openSnackBar('No hay documentos procesados para guardar');
    return;
  }

  try {
    this.isLoading = true;
    const idUser = localStorage.getItem('idusuario');
    
    let savedCount = 0;
    let errorCount = 0;

    for (const doc of documentsToSave) {
      try {
        const formData = new FormData();
        formData.append('id_user', idUser!);
        formData.append('id_file', doc.archivo_id);
        formData.append('linea', '1');
        formData.append('module', 'ADSI');
        formData.append('clasification', 'LA');
        formData.append('has_order', 'N');

        const response = await lastValueFrom(this._gdelService.saveFinalFile(formData));

        if (response.error) {
          throw new Error(response.msg || 'Error al guardar');
        }

        // Actualizar estado del documento
        doc.estado = 'final_saved';
        savedCount++;
        
        console.log(` Guardado: ${doc.nombre_del_archivo}`);

      } catch (error: any) {
        console.error(` Error guardando ${doc.nombre_del_archivo}:`, error);
        doc.estado = 'error';
        doc.error_message = error.message;
        errorCount++;
      }
    }
        
    // Actualizar tabla
    this.updateAllTableData();

    if (savedCount > 0) {
      const message = ` ${savedCount} documentos guardados exitosamente${errorCount > 0 ? `, ${errorCount} errores` : ''}`;
      this._resourcesService.openSnackBar(message);
      
      if (errorCount === 0) {
        // Solo cerrar si todos se guardaron exitosamente
        this.dialogRef.close(true);
      }
    } else {
      throw new Error('No se pudo guardar ningún documento');
    }

  } catch (error: any) {
    console.error('Error al guardar archivos:', error);
    this._resourcesService.openSnackBar('Error: ' + (error.message || 'Error desconocido'));
  } finally {
    this.isLoading = false;
  }
}



}