import { Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { MatTableDataSource } from '@angular/material/table';

export interface ExcelSheetData {
  fileName: string;
  sheets: any;
  sheetNames: string[];
  fileId: string;
 excelData?: ExcelSheetData; 
}

export interface ZipContentData {
  fileName: string;
  fileType: string;
  zipContent: {
    fileName: string;
    files: ZipFileEntry[];
    fileId: string;
    totalFiles: number;
    totalSize: number;
  };
  fileId: string;
  excelData?: ExcelSheetData; 
}

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

export interface FileItem {
  name: string;
  displayName: string;
  size: string;
  type: string;
  isDirectory: boolean;
  icon: string;
  level: number;
  parent?: string;
  fullPath: string;
  isValidated?: boolean; 
}

export interface ValidationResult {
  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;
}

@Component({
  selector: 'app-preview-file-content',
  standalone: false,
  templateUrl: './preview-file-content.component.html',
  styleUrls: ['./preview-file-content.component.css']
})
export class PreviewFileContentComponent implements OnInit {

  public fileType: 'excel' | 'zip' = 'excel';
  public fileName: string = '';
  
  public allZipFiles: FileItem[] = [];
  public visibleZipFiles: FileItem[] = [];
  public zipDataSource: MatTableDataSource<FileItem> = new MatTableDataSource();
  public zipDisplayedColumns: string[] = ['icon', 'name', 'size', 'type', 'status'];
  public totalFiles: number = 0;
  public totalSize: string = '';
  
  public searchTerm: string = '';
  public expandedFolders: Set<string> = new Set();
  
  // Variables para validación
  public validationResult: ValidationResult | null = null;
  public isValidating: boolean = false;
  public showValidationSummary: boolean = false;
  public expectedDocuments: ExcelDocumentEntry[] = [];

  constructor(
    public dialogRef: MatDialogRef<PreviewFileContentComponent>,
    @Inject(MAT_DIALOG_DATA) public data: ExcelSheetData | ZipContentData
  ) {}



  private initializeComponent(): void {
    if ('sheets' in this.data) {
      // Es un archivo Excel
      this.fileType = 'excel';
      this.fileName = this.data.fileName;
    } else {
      // Es un archivo ZIP
      this.fileType = 'zip';
      this.fileName = this.data.fileName;
      this.loadZipContent();
      
      // Si tenemos datos de Excel, extraer documentos esperados
      if (this.data.excelData) {
        this.expectedDocuments = this.extractDocumentNamesFromExcel();
        this.showValidationSummary = this.expectedDocuments.length > 0;
      }
    }
  }





  // Marcar archivos como validados en la tabla
  private markValidatedFiles(): void {
    if (!this.validationResult) return;

    const foundFilesLower = this.validationResult.foundFiles.map(f => f.toLowerCase());
    
    this.allZipFiles.forEach(file => {
      if (!file.isDirectory) {
        const fileName = (file.name.split('/').pop() || file.name).toLowerCase();
        file.isValidated = foundFilesLower.includes(fileName);
      }
    });

    this.updateVisibleFiles();
  }



  private loadZipContent(): void {
    if (!this.data || !('zipContent' in this.data)) return;
    
    const zipData = this.data.zipContent;
    this.totalFiles = zipData.totalFiles;
    this.totalSize = this.formatBytes(zipData.totalSize);
    
    // Procesar archivos del ZIP
    this.allZipFiles = this.processZipFiles(zipData.files);
    this.updateVisibleFiles();
  }

  private getFileTypeDescription(type: string): string {
    const typeMap: { [key: string]: string } = {
      'image': 'Imagen',
      'pdf': 'PDF',
      'document': 'Documento Word',
      'text': 'Texto',
      'excel': 'Excel',
      'presentation': 'Presentación',
      'archive': 'Archivo comprimido',
      'video': 'Video',
      'audio': 'Audio',
      'folder': 'Carpeta',
      'unknown': 'Desconocido'
    };
    return typeMap[type] || 'Desconocido';
  }

  private getFileIcon(type: string, isDirectory: boolean): string {
    if (isDirectory) return 'folder';
    
    const iconMap: { [key: string]: string } = {
      'image': 'image',
      'pdf': 'picture_as_pdf',
      'document': 'description',
      'text': 'text_snippet',
      'excel': 'table_chart',
      'presentation': 'slideshow',
      'archive': 'archive',
      'video': 'video_file',
      'audio': 'audio_file',
      'unknown': 'insert_drive_file'
    };
    return iconMap[type] || 'insert_drive_file';
  }

  private formatBytes(bytes: number): string {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  }

  private updateVisibleFiles(): void {
    this.visibleZipFiles = this.getVisibleFiles();
    this.applyZipFilter();
  }

  public applyZipFilter(): void {
    let filesToShow = this.visibleZipFiles;
    
    if (this.searchTerm.trim()) {
      filesToShow = this.visibleZipFiles.filter(file =>
        file.displayName.toLowerCase().includes(this.searchTerm.toLowerCase()) ||
        file.fullPath.toLowerCase().includes(this.searchTerm.toLowerCase())
      );
    }
    
    this.zipDataSource.data = filesToShow;
  }

  public toggleFolder(folderPath: string): void {
    if (this.expandedFolders.has(folderPath)) {
      this.expandedFolders.delete(folderPath);
      this.collapseSubfolders(folderPath);
    } else {
      this.expandedFolders.add(folderPath);
    }
    this.updateVisibleFiles();
  }

  private collapseSubfolders(parentPath: string): void {
    const toRemove = Array.from(this.expandedFolders).filter(path => 
      path.startsWith(parentPath + '/')
    );
    toRemove.forEach(path => this.expandedFolders.delete(path));
  }

  public isFolderExpanded(folderPath: string): boolean {
    return this.expandedFolders.has(folderPath);
  }

  public getVisibleFiles(): FileItem[] {
    const fileMap = new Map<string, FileItem>();
    this.allZipFiles.forEach(file => fileMap.set(file.fullPath, file));
    
    const buildHierarchy = (parentPath: string = '', level: number = 0): FileItem[] => {
      const result: FileItem[] = [];
      
      const children = this.allZipFiles.filter(file => {
        if (parentPath === '') {
          return file.level === 0;
        } else {
          return file.parent === parentPath;
        }
      });
      
      const sortedChildren = children.sort((a, b) => {
        if (a.isDirectory && !b.isDirectory) return -1;
        if (!a.isDirectory && b.isDirectory) return 1;
        return a.displayName.localeCompare(b.displayName);
      });
      
      sortedChildren.forEach(child => {
        result.push(child);
        
        if (child.isDirectory && this.expandedFolders.has(child.fullPath)) {
          const subChildren = buildHierarchy(child.fullPath, child.level + 1);
          result.push(...subChildren);
        }
      });
      
      return result;
    };
    
    return buildHierarchy();
  }

  private processZipFiles(files: ZipFileEntry[]): FileItem[] {
    const processedFiles: FileItem[] = [];
    const folderSet = new Set<string>();
    
    // Crear carpetas
    files.forEach(file => {
      if (file.isDirectory) {
        const cleanPath = file.name.replace(/\/$/, '');
        if (cleanPath) {
          folderSet.add(cleanPath);
        }
      } else {
        const pathParts = file.name.split('/');
        for (let i = 0; i < pathParts.length - 1; i++) {
          const folderPath = pathParts.slice(0, i + 1).join('/');
          if (folderPath) {
            folderSet.add(folderPath);
          }
        }
      }
    });

    // Crear elementos para carpetas
    Array.from(folderSet).forEach(folderPath => {
      const pathParts = folderPath.split('/');
      const level = pathParts.length - 1;
      const parent = level > 0 ? pathParts.slice(0, -1).join('/') : '';
      const displayName = pathParts[pathParts.length - 1];

      processedFiles.push({
        name: folderPath,
        displayName: displayName,
        fullPath: folderPath,
        size: '-',
        type: 'Carpeta',
        isDirectory: true,
        icon: 'folder',
        level: level,
        parent: parent,
        isValidated: false
      });
    });

    // Crear elementos para archivos
    files.forEach(file => {
      if (!file.isDirectory) {
        const pathParts = file.name.split('/');
        const level = pathParts.length - 1;
        const parent = level > 0 ? pathParts.slice(0, -1).join('/') : '';
        const displayName = pathParts[pathParts.length - 1];

        processedFiles.push({
          name: file.name,
          displayName: displayName,
          fullPath: file.name,
          size: this.formatBytes(file.size),
          type: this.getFileTypeDescription(file.type || 'unknown'),
          isDirectory: false,
          icon: this.getFileIcon(file.type || 'unknown', false),
          level: level,
          parent: parent,
          isValidated: false
        });
      }
    });

    return processedFiles;
  }

  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', '.img'
    ];
    
    const extension = fileName.toLowerCase().substring(fileName.lastIndexOf('.'));
    return validExtensions.includes(extension);
  }

  public getIndentStyle(level: number): string {
    return `padding-left: ${level * 20}px`;
  }

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

  get hasZipData(): boolean {
    return this.fileType === 'zip' && this.allZipFiles.length > 0;
  }

  get canValidate(): boolean {
    return this.hasZipData && this.expectedDocuments.length > 0;
  }

  get validationSummary(): string {
    if (!this.validationResult) {
      return `${this.expectedDocuments.length} documentos esperados`;
    }

    const { matchedCount, expectedCount } = this.validationResult.validationDetails;
    return `${matchedCount}/${expectedCount} documentos encontrados`;
  }

  get validationClass(): string {
    if (!this.validationResult) return '';
    return this.validationResult.isValid ? 'validation-success' : 'validation-error';
  }

  public getFileStatusIcon(file: FileItem): string {
    if (file.isDirectory) return '';
    
    if (this.validationResult) {
      return file.isValidated ? 'check_circle' : 'error';
    }
    
    return '';
  }

  public getFileStatusClass(file: FileItem): string {
    if (file.isDirectory || !this.validationResult) return '';
    
    return file.isValidated ? 'file-validated' : 'file-missing';
  }


private extractDocumentNamesFromExcel(): ExcelDocumentEntry[] {
  // Verificar que tengamos datos del Excel
  if (!this.data.excelData || !this.data.excelData.sheets || !this.data.excelData.sheets['CARGA DE DOCUMENTOS']) {
    console.warn('No se encontraron datos del Excel o la hoja "CARGA DE DOCUMENTOS"');
    return [];
  }

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

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

  try {
    console.log('Analizando hoja de Excel:', sheet.length, 'filas');
    
    // Recorrer desde la fila 9 hacia abajo
    for (let rowIndex = DATA_START_ROW - 1; rowIndex < sheet.length; rowIndex++) {
      const row = sheet[rowIndex];
      if (!row || !Array.isArray(row)) continue;


      const hasMainData = row[0] || row[2] || row[4];
      if (!hasMainData) continue; 

      console.log(` Procesando fila ${rowIndex + 1}:`, row);

      // 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)) {
            console.log(`Documento encontrado: ${documentName} (Columna ${column.letter}, Fila ${rowIndex + 1})`);
            
            documentEntries.push({
              rowIndex: rowIndex + 1, // +1 para mostrar número de fila real
              columnLetter: column.letter,
              columnIndex: column.index,
              documentName: documentName,
              category: column.category
            });
          } else {
            console.warn(`Archivo sin extensión válida: ${documentName} (Columna ${column.letter}, Fila ${rowIndex + 1})`);
          }
        }
      });
    }
    
    console.log(`Total de documentos encontrados en Excel: ${documentEntries.length}`);
    
  } catch (error) {
    console.error('Error al extraer nombres de documentos del Excel:', error);
  }

  return documentEntries;
}


public async validateDocuments(): Promise<void> {
  if (!this.canValidate) {
    console.warn('No se puede validar: faltan datos');
    return;
  }

  this.isValidating = true;
  
  try {
    
    await new Promise(resolve => setTimeout(resolve, 500)); // Simular procesamiento
    
    const expectedFileNames = this.expectedDocuments.map(doc => {
      console.log(`Documento esperado: ${doc.documentName} (${doc.category})`);
      return doc.documentName.toLowerCase();
    });
    
    console.log(`Total documentos esperados: ${expectedFileNames.length}`);
    
    // Obtener nombres de archivos del ZIP (solo archivos, no directorios)
    const zipFileNames = this.allZipFiles
      .filter(file => !file.isDirectory)
      .map(file => {
        // Obtener solo el nombre del archivo sin la ruta
        const fileName = file.name.split('/').pop() || file.name;
        console.log(`Archivo en ZIP: ${fileName} (path completo: ${file.name})`);
        return fileName.toLowerCase();
      });

    console.log(`Total archivos en ZIP: ${zipFileNames.length}`);

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

    expectedFileNames.forEach(expectedFile => {
      const found = zipFileNames.find(zipFile => {
        // Comparación exacta de nombres
        const matches = zipFile === expectedFile;
        if (matches) {
          console.log(`MATCH encontrado: ${expectedFile} = ${zipFile}`);
        }
        return matches;
      });

      if (found) {
        foundFiles.push(expectedFile);
      } else {
        console.log(`MISSING: ${expectedFile} no encontrado en ZIP`);
        missingFiles.push(expectedFile);
      }
    });

    // Encontrar archivos extra (en ZIP pero no en Excel)
    const extraFiles = zipFileNames.filter(zipFile => {
      const isExtra = !expectedFileNames.includes(zipFile);
      if (isExtra) {
        console.log(`EXTRA: ${zipFile} está en ZIP pero no en Excel`);
      }
      return isExtra;
    });

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

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

    // Log del resultado final
    console.log('RESULTADO DE VALIDACIÓN:');
    console.log(`   Válido: ${isValid}`);
    console.log(`   Esperados: ${expectedFileNames.length}`);
    console.log(`   Encontrados: ${foundFiles.length}`);
    console.log(`   Faltantes: ${missingFiles.length}`);
    console.log(`   Extra: ${extraFiles.length}`);
    
    if (foundFiles.length > 0) {
      console.log('Archivos encontrados:', foundFiles);
    }
    
    if (missingFiles.length > 0) {
      console.log('Archivos faltantes:', missingFiles);
    }

    // Marcar archivos validados en la tabla
    this.markValidatedFiles();
    
  } catch (error) {
    console.error('Error en validación:', error);
  } finally {
    this.isValidating = false;
  }
}


public processValidatedDocuments(): void {
  if (!this.validationResult || !this.validationResult.isValid) {
    console.warn('No se puede procesar: validación inválida');
    const message = this.validationResult 
      ? `Faltan ${this.validationResult.missingFiles.length} documentos`
      : 'Debe validar primero';
    

    alert(message);
    return;
  }

  console.log('Procesando documentos validados:', this.validationResult.foundFiles);

 
  this.dialogRef.close({
    action: 'validate',
    validationResult: this.validationResult,
    foundFiles: this.validationResult.foundFiles,
    validationDetails: this.validationResult.validationDetails
  });
}


ngOnInit(): void {
  console.log('Inicializando PreviewFileContentComponent');
  console.log('Datos recibidos:', this.data);
  
  this.initializeComponent();
  
  if (this.fileType === 'zip' && this.expectedDocuments.length > 0) {
    console.log(`Se encontraron ${this.expectedDocuments.length} documentos esperados en Excel`);
    this.expectedDocuments.forEach((doc, index) => {
      console.log(`   ${index + 1}. ${doc.documentName} (${doc.category})`);
    });
  }
}

//TEST
public debugValidation(): void {
  console.group('DEBUG DE VALIDACIÓN');
  
  console.log('Estado actual:');
  console.log('   - Tipo de archivo:', this.fileType);
  console.log('   - Puede validar:', this.canValidate);
  console.log('   - Documentos esperados:', this.expectedDocuments.length);
  console.log('   - Archivos en ZIP:', this.allZipFiles.length);
  
  console.log('Documentos esperados:');
  this.expectedDocuments.forEach(doc => {
    console.log(`   - ${doc.documentName} (${doc.category})`);
  });
  
  console.log('Archivos en ZIP:');
  this.allZipFiles.filter(f => !f.isDirectory).forEach(file => {
    const fileName = file.name.split('/').pop() || file.name;
    console.log(`   - ${fileName} (path: ${file.name})`);
  });
  
  if (this.validationResult) {
    console.log('Resultado de validación:');
    console.log('   - Es válido:', this.validationResult.isValid);
    console.log('   - Encontrados:', this.validationResult.foundFiles);
    console.log('   - Faltantes:', this.validationResult.missingFiles);
    console.log('   - Extra:', this.validationResult.extraFiles);
  }
  
  console.groupEnd();
}


get detailedValidationSummary(): string {
  if (!this.validationResult) {
    return `${this.expectedDocuments.length} documentos por validar`;
  }

  const { matchedCount, expectedCount } = this.validationResult.validationDetails;
  const missing = this.validationResult.missingFiles.length;
  const extra = this.validationResult.extraFiles.length;
  
  let summary = `${matchedCount}/${expectedCount} documentos encontrados`;
  
  if (missing > 0) {
    summary += `, ${missing} faltantes`;
  }
  
  if (extra > 0) {
    summary += `, ${extra} extra`;
  }
  
  return summary;
}

}