import { Component, EventEmitter, Input, Output } from "@angular/core";
import { CommonModule } from "@angular/common";
import {
  CdkDragDrop,
  DragDropModule,
  moveItemInArray,
} from "@angular/cdk/drag-drop";
import { PdfUploadService, PdfUploadResponse } from "./pdf-uploader.service";

export interface PdfDocument {
  id?: string;
  name: string;
  file?: File;
  url?: string;
  size?: number;
  uploadDate?: Date;
  status?: 'pending' | 'uploaded' | 'error';
  description?: string;
  fileId?: number; // ✅ NOVO: Para integração com backend
}

export interface PendingDocument {
  name: string;
  description: string;
  required: boolean;
  status: 'pending' | 'uploaded';
}

export interface AttachmentFormat {
  fileId: number;
  fileName?: string;
  fileSize?: number;
  fileType?: string;
  uploadDate?: string;
  description?: string;
}

@Component({
  selector: "app-pdf-uploader",
  standalone: true,
  imports: [CommonModule, DragDropModule],
  templateUrl: "./pdf-uploader.component.html",
  styleUrls: ["./pdf-uploader.component.scss"],
})
export class PdfUploaderComponent {
  @Input() set documents(docs: PdfDocument[]) {
    this._documents = [...docs];
    this.documentsChange.emit(this._documents);
  }

  get documents(): PdfDocument[] {
    return this._documents;
  }

  // ✅ NOVO: Suporte para formato attachment
  @Input() set attachments(attachments: AttachmentFormat[]) {
    this._documents = this.convertAttachmentsToDocuments(attachments);
    this.documentsChange.emit(this._documents);
  }

  @Output() attachmentsChange = new EventEmitter<AttachmentFormat[]>();

  private _documents: PdfDocument[] = [];

  @Input() pendingDocuments: PendingDocument[] = [];
  @Input() title: string = 'Upload de Documentos';
  @Input() subtitle: string = 'Faça o upload dos documentos do veículo';
  @Input() maxDocuments: number = 10;
  @Input() maxSizeMb: number = 10;
  @Input() allowedTypes: string[] = ["application/pdf"];
  @Input() acceptMultiple: boolean = true;
  @Input() showPendingList: boolean = true;

  @Output() documentsChange = new EventEmitter<PdfDocument[]>();
  @Output() filesChange = new EventEmitter<File[]>();
  @Output() error = new EventEmitter<string>();
  @Output() documentUploaded = new EventEmitter<PdfDocument>();

  selectedFiles: File[] = [];
  isDragOver: boolean = false;
  previewDocument: PdfDocument | null = null;

  constructor(private pdfUploadService: PdfUploadService) {}

  onFileSelected(event: Event) {
    const input = event.target as HTMLInputElement;
    if (!input.files) return;

    const files = Array.from(input.files);
    this.processFiles(files);
    
    // Limpar o input para permitir selecionar o mesmo arquivo novamente
    input.value = '';
  }

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

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

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

    const files = Array.from(event.dataTransfer?.files || []);
    this.processFiles(files);
  }

  private processFiles(files: File[]) {
    if (this.documents.length + files.length > this.maxDocuments) {
      this.error.emit(`Você pode enviar no máximo ${this.maxDocuments} documentos.`);
      return;
    }

    for (const file of files) {
      if (!this.allowedTypes.includes(file.type)) {
        this.error.emit(`Formato inválido: ${file.type}. Apenas arquivos PDF são aceitos.`);
        continue;
      }

      const sizeMb = file.size / (1024 * 1024);
      if (sizeMb > this.maxSizeMb) {
        this.error.emit(`O arquivo "${file.name}" excede ${this.maxSizeMb}MB.`);
        continue;
      }

      const pdfDoc: PdfDocument = {
        id: this.generateId(),
        name: file.name,
        file: file,
        size: file.size,
        uploadDate: new Date(),
        status: 'pending'
      };

      this._documents.push(pdfDoc);
      this.selectedFiles.push(file);
    }

    this.documentsChange.emit(this._documents);
    this.filesChange.emit(this.selectedFiles);
  }

  private generateId(): string {
    return Math.random().toString(36).substr(2, 9);
  }

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

  openDocument(document: PdfDocument) {
    if (document.file) {
      const url = URL.createObjectURL(document.file);
      window.open(url, '_blank');
    } else if (document.url) {
      window.open(document.url, '_blank');
    }
  }

  async removeDocument(index: number) {
    const removedDoc = this.documents[index];
    
    // Tentar deletar do servidor se tiver fileId
    if (removedDoc.fileId) {
      const deleted = await this.deleteDocumentFromServer(removedDoc);
      if (!deleted) {
        // Se não conseguiu deletar do servidor, não remove da lista
        return;
      }
    }
    
    this.documents.splice(index, 1);
    this.documentsChange.emit(this.documents);

    // Remover da lista de arquivos selecionados se existir
    const fileIndex = this.selectedFiles.findIndex(f => f.name === removedDoc.name);
    if (fileIndex > -1) {
      this.selectedFiles.splice(fileIndex, 1);
      this.filesChange.emit(this.selectedFiles);
    }

    // ✅ NOVO: Emitir mudanças no formato attachment
    this.emitAttachmentChanges();
  }

  clearAll() {
    this._documents = [];
    this.documentsChange.emit(this._documents);
    this.selectedFiles = [];
    this.filesChange.emit([]);
  }

  onDocumentDrop(event: CdkDragDrop<PdfDocument[]>) {
    moveItemInArray(
      this.documents,
      event.previousIndex,
      event.currentIndex
    );
    this.documentsChange.emit(this._documents);

    if (this.selectedFiles.length === this._documents.length) {
      moveItemInArray(
        this.selectedFiles,
        event.previousIndex,
        event.currentIndex
      );
      this.filesChange.emit(this.selectedFiles);
    }
  }

  sendDocument(pendingDoc: PendingDocument) {
    // Método para enviar documento específico
    // Implementar lógica de envio conforme necessário
    console.log('Enviando documento:', pendingDoc);
  }

  getDocumentIcon(document: PdfDocument): string {
    return 'fas fa-file-pdf';
  }

  isPendingDocumentUploaded(pendingDoc: PendingDocument): boolean {
    return this.documents.some(doc => 
      doc.name.toLowerCase().includes(pendingDoc.name.toLowerCase()) ||
      doc.description?.toLowerCase().includes(pendingDoc.name.toLowerCase())
    );
  }

  // ========================================
  // 🔄 MÉTODOS DE CONVERSÃO ATTACHMENT
  // ========================================

  /**
   * Converte attachments do backend para PdfDocuments
   */
  private convertAttachmentsToDocuments(attachments: AttachmentFormat[]): PdfDocument[] {
    return attachments.map(attachment => ({
      id: attachment.fileId.toString(),
      name: attachment.fileName || `Documento ${attachment.fileId}`,
      fileId: attachment.fileId,
      size: attachment.fileSize,
      uploadDate: attachment.uploadDate ? new Date(attachment.uploadDate) : undefined,
      status: 'uploaded' as const,
      description: attachment.description
    }));
  }

  /**
   * Converte PdfDocuments para formato attachment do backend
   */
  convertDocumentsToAttachments(): AttachmentFormat[] {
    return this.documents
      .filter(doc => doc.fileId && doc.status === 'uploaded')
      .map(doc => ({
        fileId: doc.fileId!,
        fileName: doc.name,
        fileSize: doc.size,
        fileType: 'application/pdf',
        uploadDate: doc.uploadDate?.toISOString(),
        description: doc.description
      }));
  }

  /**
   * Emite mudanças no formato attachment
   */
  private emitAttachmentChanges(): void {
    const attachments = this.convertDocumentsToAttachments();
    this.attachmentsChange.emit(attachments);
  }

  /**
   * Método para atualizar fileId após upload bem-sucedido
   */
  updateDocumentFileId(documentId: string, fileId: number): void {
    const doc = this.documents.find(d => d.id === documentId);
    if (doc) {
      doc.fileId = fileId;
      doc.status = 'uploaded';
      this.emitAttachmentChanges();
    }
  }

  // ========================================
  // 🚀 MÉTODOS DE UPLOAD COM SERVIÇO
  // ========================================

  /**
   * Upload real de arquivos usando PdfUploadService
   */
  async uploadFilesToServer(files: File[], entityType?: string, entityId?: string): Promise<void> {
    for (const file of files) {
      try {
        console.log(`📤 Iniciando upload real do arquivo: ${file.name}`);
        
        // Buscar documento correspondente na lista
        const document = this.documents.find(doc => doc.file === file);
        if (document) {
          document.status = 'pending';
        }

        // Upload usando o serviço
        const response = await this.pdfUploadService.uploadPdfDirect(file, entityType, entityId).toPromise();
        
        if (response) {
          console.log(`✅ Upload concluído para: ${file.name}`, response);
          
          // Atualizar documento com dados do servidor
          if (document) {
            document.fileId = response.fileId;
            document.status = 'uploaded';
            document.uploadDate = new Date(response.uploadDate);
            document.size = response.fileSize;
            
            // Emitir evento de documento enviado
            this.documentUploaded.emit(document);
          }
          
          // Atualizar attachments
          this.emitAttachmentChanges();
        }
        
      } catch (error) {
        console.error(`❌ Erro no upload de ${file.name}:`, error);
        
        // Atualizar status para erro
        const document = this.documents.find(doc => doc.file === file);
        if (document) {
          document.status = 'error';
        }
        
        // Emitir erro
        this.error.emit(`Erro no upload de ${file.name}: ${error}`);
      }
    }
  }

  /**
   * Carrega documentos existentes por IDs
   */
  async loadExistingDocuments(fileIds: number[]): Promise<void> {
    try {
      console.log('📄 Carregando documentos existentes:', fileIds);
      
      const documents = await this.pdfUploadService.getPdfsByIds(fileIds).toPromise();
      
      if (documents) {
        const pdfDocuments: PdfDocument[] = documents.map(doc => ({
          id: doc.fileId.toString(),
          name: doc.fileName,
          fileId: doc.fileId,
          size: doc.fileSize,
          uploadDate: new Date(doc.uploadDate),
          status: 'uploaded',
          url: doc.downloadUrl
        }));
        
        this._documents = [...this._documents, ...pdfDocuments];
        this.documentsChange.emit(this._documents);
        this.emitAttachmentChanges();
        
        console.log(`✅ ${documents.length} documentos carregados`);
      }
      
    } catch (error) {
      console.error('❌ Erro ao carregar documentos existentes:', error);
      this.error.emit(`Erro ao carregar documentos: ${error}`);
    }
  }

  /**
   * Remove documento do servidor
   */
  async deleteDocumentFromServer(document: PdfDocument): Promise<boolean> {
    if (!document.fileId) {
      return true; // Documento apenas local, não precisa deletar do servidor
    }

    try {
      console.log(`🗑️ Deletando documento do servidor: ${document.name} (ID: ${document.fileId})`);
      
      await this.pdfUploadService.deletePdf(document.fileId).toPromise();
      
      console.log(`✅ Documento deletado do servidor: ${document.name}`);
      return true;
      
    } catch (error) {
      console.error(`❌ Erro ao deletar documento ${document.name}:`, error);
      this.error.emit(`Erro ao deletar documento: ${error}`);
      return false;
    }
  }

  /**
   * Atualiza metadados de um documento no servidor
   */
  async updateDocumentMetadata(document: PdfDocument, metadata: { fileName?: string; description?: string }): Promise<void> {
    if (!document.fileId) {
      return;
    }

    try {
      console.log(`📝 Atualizando metadados do documento: ${document.name}`);
      
      const response = await this.pdfUploadService.updatePdfMetadata(document.fileId, metadata).toPromise();
      
      if (response) {
        // Atualizar documento local
        document.name = response.fileName;
        document.description = metadata.description;
        
        console.log(`✅ Metadados atualizados: ${document.name}`);
      }
      
    } catch (error) {
      console.error(`❌ Erro ao atualizar metadados de ${document.name}:`, error);
      this.error.emit(`Erro ao atualizar documento: ${error}`);
    }
  }
}
