import os
import hashlib
import threading
import json
from flask import Flask, render_template_string, request, jsonify
from werkzeug.utils import secure_filename

app = Flask(__name__)

# Lock para sincronizar escritas paralelas
file_locks = {}
locks_lock = threading.Lock()

# Configurações
UPLOAD_FOLDER = 'uploads'
TEMP_FOLDER = 'temp_uploads'
FOLDERS_CONFIG = 'folders_config.json'
CHUNK_SIZE = 2 * 1024 * 1024  # 2MB por chunk
ALLOWED_EXTENSIONS = {'mp4', 'avi', 'mov', 'mkv', 'webm', 'flv', 'pdf', 'doc', 'docx', 
                      'txt', 'zip', 'rar', '7z', 'jpg', 'jpeg', 'png', 'gif', 'mp3', 
                      'wav', 'xlsx', 'xls', 'ppt', 'pptx'}

# Cria pastas
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(TEMP_FOLDER, exist_ok=True)

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['TEMP_FOLDER'] = TEMP_FOLDER
app.config['MAX_CONTENT_LENGTH'] = None

print("=" * 60)
print("SERVIDOR INICIADO")
print(f"Pasta uploads: {os.path.abspath(UPLOAD_FOLDER)}")
print(f"Pasta temp: {os.path.abspath(TEMP_FOLDER)}")
print(f"Chunk size: {CHUNK_SIZE} bytes ({CHUNK_SIZE/1024}KB)")
print("=" * 60)

# Gerenciamento de pastas personalizadas
def load_folders():
    """Carrega configuração de pastas"""
    if os.path.exists(FOLDERS_CONFIG):
        with open(FOLDERS_CONFIG, 'r', encoding='utf-8') as f:
            return json.load(f)
    return {}

def save_folders(folders):
    """Salva configuração de pastas"""
    with open(FOLDERS_CONFIG, 'w', encoding='utf-8') as f:
        json.dump(folders, f, indent=2, ensure_ascii=False)

HTML_TEMPLATE = """
<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Upload com Pastas Personalizadas</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 20px;
        }
        
        .container {
            background: white;
            border-radius: 20px;
            padding: 40px;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
            max-width: 700px;
            width: 100%;
            max-height: 90vh;
            overflow-y: auto;
        }
        
        h1 { color: #333; margin-bottom: 10px; text-align: center; }
        .subtitle { text-align: center; color: #666; margin-bottom: 30px; font-size: 14px; }
        
        /* Gerenciamento de Pastas */
        .folder-section {
            background: #f8f9ff;
            padding: 20px;
            border-radius: 10px;
            margin-bottom: 20px;
        }
        
        .folder-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
        }
        
        .folder-header h2 { font-size: 18px; color: #333; }
        
        .folder-input-group {
            display: flex;
            gap: 10px;
            margin-bottom: 15px;
        }
        
        .folder-input-group input {
            flex: 1;
            padding: 10px;
            border: 2px solid #e0e0e0;
            border-radius: 8px;
            font-size: 14px;
        }
        
        .folder-input-group input:focus {
            outline: none;
            border-color: #667eea;
        }
        
        .folder-list {
            display: flex;
            flex-direction: column;
            gap: 8px;
            max-height: 200px;
            overflow-y: auto;
        }
        
        .folder-item {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 12px;
            background: white;
            border-radius: 8px;
            border: 2px solid transparent;
            cursor: pointer;
            transition: all 0.3s;
        }
        
        .folder-item:hover { border-color: #667eea; }
        .folder-item.selected { background: #667eea; color: white; border-color: #667eea; }
        
        .folder-info { display: flex; align-items: center; gap: 10px; flex: 1; }
        .folder-icon { font-size: 20px; }
        .folder-details { flex: 1; }
        .folder-name { font-weight: 600; }
        .folder-path { font-size: 11px; opacity: 0.7; }
        
        .folder-item.selected .folder-path { opacity: 0.9; }
        
        .folder-actions {
            display: flex;
            gap: 5px;
        }
        
        .btn-icon {
            background: none;
            border: none;
            cursor: pointer;
            font-size: 18px;
            padding: 5px;
            opacity: 0.6;
            transition: all 0.3s;
        }
        
        .btn-icon:hover { opacity: 1; transform: scale(1.2); }
        .folder-item.selected .btn-icon { opacity: 0.8; }
        
        /* Upload Area */
        .upload-area {
            border: 3px dashed #667eea;
            border-radius: 15px;
            padding: 40px;
            text-align: center;
            cursor: pointer;
            transition: all 0.3s;
            margin-bottom: 20px;
        }
        
        .upload-area:hover { border-color: #764ba2; background: #f8f9ff; }
        .upload-area.dragover { background: #e8ebff; border-color: #764ba2; }
        .upload-area.disabled {
            opacity: 0.5;
            cursor: not-allowed;
            border-color: #ccc;
        }
        
        .upload-icon { font-size: 48px; margin-bottom: 10px; }
        input[type="file"] { display: none; }
        
        .selected-folder-info {
            background: #e8ebff;
            padding: 10px;
            border-radius: 8px;
            margin-bottom: 15px;
            text-align: center;
            font-size: 14px;
            display: none;
        }
        
        .selected-folder-info.active { display: block; }
        .selected-folder-info strong { color: #667eea; }
        
        .file-info {
            background: #f8f9ff;
            padding: 15px;
            border-radius: 10px;
            margin: 20px 0;
            display: none;
        }
        
        .file-info.active { display: block; }
        
        .file-list {
            max-height: 200px;
            overflow-y: auto;
            margin-top: 10px;
        }
        
        .file-item {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 10px;
            background: white;
            border-radius: 6px;
            margin-bottom: 8px;
            border: 1px solid #e0e0e0;
        }
        
        .file-item-info { flex: 1; }
        .file-item-name { font-weight: 600; font-size: 14px; }
        .file-item-size { font-size: 12px; color: #666; }
        
        .file-item-status {
            font-size: 12px;
            padding: 4px 8px;
            border-radius: 4px;
            font-weight: 500;
        }
        
        .file-item-status.pending { background: #f3f4f6; color: #666; }
        .file-item-status.uploading { background: #dbeafe; color: #1d4ed8; }
        .file-item-status.completed { background: #d1fae5; color: #065f46; }
        .file-item-status.error { background: #fee2e2; color: #991b1b; }
        
        .file-item-progress {
            width: 100%;
            height: 4px;
            background: #e0e0e0;
            border-radius: 2px;
            margin-top: 5px;
            overflow: hidden;
        }
        
        .file-item-progress-bar {
            height: 100%;
            background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
            width: 0%;
            transition: width 0.3s;
        }
        
        .btn-remove-file {
            background: #fee2e2;
            color: #991b1b;
            border: none;
            padding: 5px 10px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
            margin-left: 10px;
        }
        
        .btn-remove-file:hover { background: #fecaca; }
        
        .progress-container {
            background: #e0e0e0;
            border-radius: 10px;
            height: 30px;
            margin: 20px 0;
            overflow: hidden;
            position: relative;
        }
        
        .progress-bar {
            background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
            height: 100%;
            width: 0%;
            transition: width 0.3s;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-weight: bold;
        }
        
        .buttons { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
        
        button {
            padding: 12px 30px;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            cursor: pointer;
            transition: all 0.3s;
            font-weight: 500;
        }
        
        .btn-primary {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
        }
        
        .btn-primary:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
        }
        
        .btn-secondary { background: #e0e0e0; color: #333; }
        .btn-secondary:hover { background: #d0d0d0; }
        
        .btn-small {
            padding: 8px 16px;
            font-size: 14px;
        }
        
        .status { text-align: center; margin-top: 20px; font-weight: 500; }
        .status.success { color: #10b981; }
        .status.error { color: #ef4444; }
        .status.warning { color: #f59e0b; }
        
        .debug {
            background: #f0f0f0;
            padding: 10px;
            margin-top: 20px;
            border-radius: 5px;
            font-family: monospace;
            font-size: 12px;
            max-height: 150px;
            overflow-y: auto;
            display: none;
        }
        
        .debug.active { display: block; }
    </style>
</head>
<body>
    <div class="container">
        <h1>📁 Upload com Pastas</h1>
        <p class="subtitle">Organize seus arquivos em pastas personalizadas</p>
        
        <!-- Gerenciamento de Pastas -->
        <div class="folder-section">
            <div class="folder-header">
                <h2>📂 Minhas Pastas</h2>
            </div>
            
            <div class="folder-input-group">
                <input type="text" id="folderNameInput" placeholder="Nome da pasta (ex: Vídeos 2024)">
                <button class="btn-primary btn-small" id="createFolderBtn">Criar</button>
            </div>
            
            <div class="folder-list" id="folderList">
                <div style="text-align: center; padding: 20px; color: #999;">
                    Nenhuma pasta criada ainda
                </div>
            </div>
        </div>
        
        <!-- Info da Pasta Selecionada -->
        <div class="selected-folder-info" id="selectedFolderInfo">
            📁 Enviando para: <strong id="selectedFolderName"></strong>
        </div>
        
        <!-- Área de Upload -->
        <div class="upload-area disabled" id="uploadArea">
            <div class="upload-icon">☁️</div>
            <p id="uploadAreaText">Selecione uma pasta primeiro</p>
            <p style="font-size: 12px; color: #666; margin-top: 10px;">
                Todos os tipos de arquivo são aceitos
            </p>
        </div>
        
        <input type="file" id="fileInput" multiple>
        
        <div class="file-info" id="fileInfo">
            <p><strong>Arquivos selecionados:</strong> <span id="fileCount">0</span></p>
            <p><strong>Tamanho total:</strong> <span id="totalSize">0 Bytes</span></p>
            <div class="file-list" id="fileList"></div>
        </div>
        
        <div class="progress-container" id="progressContainer" style="display: none;">
            <div class="progress-bar" id="progressBar">0%</div>
        </div>
        
        <div class="buttons">
            <button class="btn-primary" id="uploadBtn" style="display: none;">Iniciar Upload</button>
            <button class="btn-secondary" id="pauseBtn" style="display: none;">Pausar</button>
            <button class="btn-secondary" id="cancelBtn" style="display: none;">Cancelar</button>
        </div>
        
        <div class="status" id="status"></div>
        <div class="debug" id="debug"></div>
    </div>

    <script>
        // Elementos
        const folderNameInput = document.getElementById('folderNameInput');
        const createFolderBtn = document.getElementById('createFolderBtn');
        const folderList = document.getElementById('folderList');
        const selectedFolderInfo = document.getElementById('selectedFolderInfo');
        const selectedFolderName = document.getElementById('selectedFolderName');
        const uploadArea = document.getElementById('uploadArea');
        const uploadAreaText = document.getElementById('uploadAreaText');
        const fileInput = document.getElementById('fileInput');
        const fileInfo = document.getElementById('fileInfo');
        const fileCount = document.getElementById('fileCount');
        const totalSize = document.getElementById('totalSize');
        const fileListEl = document.getElementById('fileList');
        const progressContainer = document.getElementById('progressContainer');
        const progressBar = document.getElementById('progressBar');
        const uploadBtn = document.getElementById('uploadBtn');
        const pauseBtn = document.getElementById('pauseBtn');
        const cancelBtn = document.getElementById('cancelBtn');
        const status = document.getElementById('status');
        const debug = document.getElementById('debug');

        let selectedFolder = null;
        let selectedFiles = [];
        let currentFileIndex = 0;
        let currentFileHash = null;
        let uploadedSize = 0;
        let isPaused = false;
        let isUploading = false;
        const CHUNK_SIZE = 2 * 1024 * 1024;
        
        // Armazena progresso de cada arquivo
        let filesProgress = {};

        function log(msg) {
            console.log(msg);
            debug.classList.add('active');
            debug.innerHTML += msg + '<br>';
            debug.scrollTop = debug.scrollHeight;
        }

        // Carrega pastas ao iniciar
        loadFolders();

        // Criar nova pasta
        createFolderBtn.addEventListener('click', async () => {
            const folderName = folderNameInput.value.trim();
            
            if (!folderName) {
                showStatus('❌ Digite um nome para a pasta', 'error');
                return;
            }
            
            try {
                const response = await fetch('/create-folder', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({name: folderName})
                });
                
                const data = await response.json();
                
                if (!response.ok) {
                    throw new Error(data.error || 'Erro ao criar pasta');
                }
                
                showStatus('✅ Pasta criada!', 'success');
                folderNameInput.value = '';
                loadFolders();
                
            } catch (error) {
                showStatus('❌ ' + error.message, 'error');
            }
        });

        // Carregar lista de pastas
        async function loadFolders() {
            try {
                const response = await fetch('/list-folders');
                const data = await response.json();
                
                if (Object.keys(data).length === 0) {
                    folderList.innerHTML = `
                        <div style="text-align: center; padding: 20px; color: #999;">
                            Nenhuma pasta criada ainda
                        </div>
                    `;
                    return;
                }
                
                folderList.innerHTML = '';
                
                for (const [id, folder] of Object.entries(data)) {
                    const folderItem = document.createElement('div');
                    folderItem.className = 'folder-item';
                    folderItem.dataset.folderId = id;
                    
                    folderItem.innerHTML = `
                        <div class="folder-info">
                            <div class="folder-icon">📁</div>
                            <div class="folder-details">
                                <div class="folder-name">${folder.name}</div>
                                <div class="folder-path">${folder.path}</div>
                            </div>
                        </div>
                        <div class="folder-actions">
                            <button class="btn-icon delete-folder" title="Excluir pasta">🗑️</button>
                        </div>
                    `;
                    
                    // Selecionar pasta
                    folderItem.addEventListener('click', (e) => {
                        if (!e.target.classList.contains('delete-folder')) {
                            selectFolder(id, folder);
                        }
                    });
                    
                    // Excluir pasta
                    folderItem.querySelector('.delete-folder').addEventListener('click', async (e) => {
                        e.stopPropagation();
                        if (confirm(`Excluir a pasta "${folder.name}"?`)) {
                            await deleteFolder(id);
                        }
                    });
                    
                    folderList.appendChild(folderItem);
                }
                
            } catch (error) {
                log('Erro ao carregar pastas: ' + error.message);
            }
        }

        // Selecionar pasta
        function selectFolder(id, folder) {
            selectedFolder = {id, ...folder};
            
            // Atualiza UI
            document.querySelectorAll('.folder-item').forEach(item => {
                item.classList.remove('selected');
            });
            
            document.querySelector(`[data-folder-id="${id}"]`)?.classList.add('selected');
            
            selectedFolderInfo.classList.add('active');
            selectedFolderName.textContent = folder.name;
            
            uploadArea.classList.remove('disabled');
            uploadAreaText.textContent = 'Clique ou arraste seus arquivos aqui';
            
            log('Pasta selecionada: ' + folder.name);
        }

        // Excluir pasta
        async function deleteFolder(id) {
            try {
                const response = await fetch('/delete-folder', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({folderId: id})
                });
                
                if (!response.ok) throw new Error('Erro ao excluir');
                
                if (selectedFolder && selectedFolder.id === id) {
                    selectedFolder = null;
                    selectedFolderInfo.classList.remove('active');
                    uploadArea.classList.add('disabled');
                    uploadAreaText.textContent = 'Selecione uma pasta primeiro';
                }
                
                showStatus('✅ Pasta excluída', 'success');
                loadFolders();
                
            } catch (error) {
                showStatus('❌ ' + error.message, 'error');
            }
        }

        // Upload de arquivo
        uploadArea.addEventListener('click', () => {
            if (!uploadArea.classList.contains('disabled')) {
                fileInput.click();
            }
        });
        
        uploadArea.addEventListener('dragover', (e) => {
            e.preventDefault();
            if (!uploadArea.classList.contains('disabled')) {
                uploadArea.classList.add('dragover');
            }
        });
        
        uploadArea.addEventListener('dragleave', () => {
            uploadArea.classList.remove('dragover');
        });
        
        uploadArea.addEventListener('drop', (e) => {
            e.preventDefault();
            uploadArea.classList.remove('dragover');
            if (!uploadArea.classList.contains('disabled') && e.dataTransfer.files.length > 0) {
                handleFileSelect(Array.from(e.dataTransfer.files));
            }
        });
        
        fileInput.addEventListener('change', (e) => {
            if (e.target.files.length > 0) handleFileSelect(Array.from(e.target.files));
        });

        function handleFileSelect(files) {
            if (!selectedFolder) {
                showStatus('❌ Selecione uma pasta primeiro', 'error');
                return;
            }
            
            log(`${files.length} arquivo(s) selecionado(s)`);
            selectedFiles = files;
            
            fileCount.textContent = files.length;
            const total = files.reduce((sum, f) => sum + f.size, 0);
            totalSize.textContent = formatFileSize(total);
            
            fileInfo.classList.add('active');
            uploadBtn.style.display = 'inline-block';
            uploadBtn.textContent = 'Iniciar Upload';
            
            // Renderiza lista de arquivos
            fileListEl.innerHTML = '';
            files.forEach((file, index) => {
                const fileItem = document.createElement('div');
                fileItem.className = 'file-item';
                fileItem.dataset.fileIndex = index;
                
                fileItem.innerHTML = `
                    <div class="file-item-info">
                        <div class="file-item-name">📄 ${file.name}</div>
                        <div class="file-item-size">${formatFileSize(file.size)}</div>
                        <div class="file-item-progress">
                            <div class="file-item-progress-bar" id="progress-${index}"></div>
                        </div>
                    </div>
                    <div class="file-item-status pending" id="status-${index}">Pendente</div>
                    <button class="btn-remove-file" onclick="removeFile(${index})">✕</button>
                `;
                
                fileListEl.appendChild(fileItem);
                
                filesProgress[index] = {
                    file: file,
                    status: 'pending',
                    progress: 0,
                    uploadedSize: 0,
                    fileHash: null
                };
            });
        }
        
        window.removeFile = function(index) {
            if (isUploading) {
                showStatus('❌ Não é possível remover durante upload', 'error');
                return;
            }
            
            selectedFiles.splice(index, 1);
            delete filesProgress[index];
            
            if (selectedFiles.length === 0) {
                resetUpload();
            } else {
                handleFileSelect(selectedFiles);
            }
        };

        uploadBtn.addEventListener('click', startUpload);
        pauseBtn.addEventListener('click', pauseUpload);
        cancelBtn.addEventListener('click', cancelUpload);

        async function startUpload() {
            if (selectedFiles.length === 0 || !selectedFolder) return;
            
            log('=== INICIANDO UPLOAD DE MÚLTIPLOS ARQUIVOS ===');
            isUploading = true;
            isPaused = false;
            uploadBtn.style.display = 'none';
            pauseBtn.style.display = 'inline-block';
            cancelBtn.style.display = 'inline-block';
            progressContainer.style.display = 'block';
            
            showStatus('Enviando arquivos...', '');
            
            // Processa cada arquivo sequencialmente
            for (let i = 0; i < selectedFiles.length; i++) {
                if (isPaused) break;
                
                currentFileIndex = i;
                const file = selectedFiles[i];
                
                log(`\n--- Arquivo ${i + 1}/${selectedFiles.length}: ${file.name} ---`);
                updateFileStatus(i, 'uploading', 'Enviando...');
                
                try {
                    // Verifica se já existe upload parcial
                    const checkResponse = await fetch('/check-upload', {
                        method: 'POST',
                        headers: {'Content-Type': 'application/json'},
                        body: JSON.stringify({
                            filename: file.name,
                            fileSize: file.size,
                            folderId: selectedFolder.id
                        })
                    });
                    
                    const checkData = await checkResponse.json();
                    currentFileHash = checkData.fileHash;
                    uploadedSize = checkData.uploadedSize || 0;
                    
                    filesProgress[i].fileHash = currentFileHash;
                    filesProgress[i].uploadedSize = uploadedSize;
                    
                    // Faz upload dos chunks
                    await uploadFileChunks(file, i);
                    
                    if (!isPaused) {
                        updateFileStatus(i, 'completed', '✓ Completo');
                        updateFileProgress(i, 100);
                        log(`✓ Arquivo ${i + 1} completo`);
                    }
                    
                } catch (error) {
                    log(`✗ Erro no arquivo ${i + 1}: ${error.message}`);
                    updateFileStatus(i, 'error', '✗ Erro');
                    showStatus(`❌ Erro: ${error.message}`, 'error');
                    pauseUpload();
                    return;
                }
            }
            
            if (!isPaused) {
                updateProgress(100);
                showStatus('✅ Todos os arquivos enviados!', 'success');
                log('=== UPLOAD COMPLETO ===');
                setTimeout(resetUpload, 2000);
            }
        }

        async function uploadFileChunks(file, fileIndex) {
            let chunkNumber = 0;
            
            while (uploadedSize < file.size && !isPaused) {
                const start = uploadedSize;
                const end = Math.min(start + CHUNK_SIZE, file.size);
                const chunk = file.slice(start, end);
                
                chunkNumber++;
                
                const formData = new FormData();
                formData.append('chunk', chunk);
                formData.append('filename', file.name);
                formData.append('fileHash', currentFileHash);
                formData.append('chunkStart', start);
                formData.append('totalSize', file.size);
                formData.append('folderId', selectedFolder.id);
                
                try {
                    const controller = new AbortController();
                    const timeoutId = setTimeout(() => controller.abort(), 30000);
                    
                    const response = await fetch('/upload-chunk', {
                        method: 'POST',
                        body: formData,
                        signal: controller.signal
                    });
                    
                    clearTimeout(timeoutId);
                    
                    if (!response.ok) {
                        const errorText = await response.text();
                        throw new Error('HTTP ' + response.status);
                    }
                    
                    const data = await response.json();
                    
                    if (data.status === 'completed') {
                        updateFileProgress(fileIndex, 100);
                        uploadedSize = file.size;
                        return;
                    }
                    
                    uploadedSize = data.uploadedSize;
                    const fileProgress = (uploadedSize / file.size) * 100;
                    updateFileProgress(fileIndex, fileProgress);
                    
                    // Atualiza progresso geral
                    const totalProgress = calculateTotalProgress();
                    updateProgress(totalProgress);
                    
                } catch (error) {
                    throw error;
                }
            }
        }
        
        function calculateTotalProgress() {
            let totalBytes = 0;
            let uploadedBytes = 0;
            
            selectedFiles.forEach((file, index) => {
                totalBytes += file.size;
                if (index < currentFileIndex) {
                    uploadedBytes += file.size;
                } else if (index === currentFileIndex) {
                    uploadedBytes += uploadedSize;
                }
            });
            
            return (uploadedBytes / totalBytes) * 100;
        }
        
        function updateFileStatus(index, status, text) {
            const statusEl = document.getElementById(`status-${index}`);
            if (statusEl) {
                statusEl.className = `file-item-status ${status}`;
                statusEl.textContent = text;
            }
            filesProgress[index].status = status;
        }
        
        function updateFileProgress(index, percent) {
            const progressEl = document.getElementById(`progress-${index}`);
            if (progressEl) {
                progressEl.style.width = percent + '%';
            }
            filesProgress[index].progress = percent;
        }

        function pauseUpload() {
            isPaused = true;
            isUploading = false;
            uploadBtn.style.display = 'inline-block';
            uploadBtn.textContent = 'Continuar Upload';
            pauseBtn.style.display = 'none';
            showStatus('⏸️ Upload pausado', 'warning');
        }

        async function cancelUpload() {
            isPaused = true;
            isUploading = false;
            
            // Cancela arquivo atual
            if (currentFileHash) {
                await fetch('/cancel-upload', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({fileHash: currentFileHash})
                });
            }
            
            resetUpload();
            showStatus('Upload cancelado', 'error');
        }

        function resetUpload() {
            selectedFiles = [];
            currentFileIndex = 0;
            currentFileHash = null;
            uploadedSize = 0;
            isPaused = false;
            isUploading = false;
            filesProgress = {};
            
            fileInfo.classList.remove('active');
            progressContainer.style.display = 'none';
            uploadBtn.style.display = 'none';
            pauseBtn.style.display = 'none';
            cancelBtn.style.display = 'none';
            
            updateProgress(0);
            fileInput.value = '';
            fileListEl.innerHTML = '';
        }

        function updateProgress(percent) {
            progressBar.style.width = percent + '%';
            progressBar.textContent = percent.toFixed(1) + '%';
        }

        function showStatus(message, type) {
            status.textContent = message;
            status.className = 'status ' + type;
        }

        function formatFileSize(bytes) {
            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 Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
        }

        window.addEventListener('beforeunload', (e) => {
            if (isUploading) {
                e.preventDefault();
                e.returnValue = 'Upload em progresso';
            }
        });
    </script>
</body>
</html>
"""

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

def get_file_hash(filename, file_size, folder_id):
    return hashlib.md5(f"{folder_id}_{filename}_{file_size}".encode()).hexdigest()

@app.route('/')
def index():
    return render_template_string(HTML_TEMPLATE)

@app.route('/create-folder', methods=['POST'])
def create_folder():
    try:
        data = request.get_json()
        folder_name = secure_filename(data.get('name', '').strip())
        
        if not folder_name:
            return jsonify({'error': 'Nome inválido'}), 400
        
        folders = load_folders()
        folder_id = hashlib.md5(folder_name.encode()).hexdigest()[:8]
        
        # Verifica duplicados
        for fid, fdata in folders.items():
            if fdata['name'] == folder_name:
                return jsonify({'error': 'Pasta já existe'}), 400
        
        folder_path = os.path.join(app.config['UPLOAD_FOLDER'], folder_name)
        os.makedirs(folder_path, exist_ok=True)
        
        folders[folder_id] = {
            'name': folder_name,
            'path': folder_path,
            'created': os.path.getctime(folder_path)
        }
        
        save_folders(folders)
        print(f"[FOLDER] Criada: {folder_name} (ID: {folder_id})")
        
        return jsonify({'id': folder_id, 'folder': folders[folder_id]})
        
    except Exception as e:
        print(f"[FOLDER] ERRO: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/list-folders', methods=['GET'])
def list_folders():
    try:
        folders = load_folders()
        return jsonify(folders)
    except Exception as e:
        print(f"[LIST] ERRO: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/delete-folder', methods=['POST'])
def delete_folder():
    try:
        data = request.get_json()
        folder_id = data.get('folderId')
        
        folders = load_folders()
        
        if folder_id not in folders:
            return jsonify({'error': 'Pasta não encontrada'}), 404
        
        folder_path = folders[folder_id]['path']
        
        # Remove pasta do disco se estiver vazia
        if os.path.exists(folder_path) and not os.listdir(folder_path):
            os.rmdir(folder_path)
        
        del folders[folder_id]
        save_folders(folders)
        
        print(f"[FOLDER] Excluída: {folder_id}")
        return jsonify({'status': 'deleted'})
        
    except Exception as e:
        print(f"[DELETE] ERRO: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/check-upload', methods=['POST'])
def check_upload():
    try:
        data = request.get_json()
        filename = secure_filename(data.get('filename'))
        file_size = data.get('fileSize')
        folder_id = data.get('folderId')
        
        print(f"\n[CHECK] Arquivo: {filename}, Tamanho: {file_size}, Pasta: {folder_id}")
        
        folders = load_folders()
        if folder_id not in folders:
            return jsonify({'error': 'Pasta não encontrada'}), 404
        
        file_hash = get_file_hash(filename, file_size, folder_id)
        temp_path = os.path.join(app.config['TEMP_FOLDER'], file_hash)
        
        uploaded_size = 0
        if os.path.exists(temp_path):
            uploaded_size = os.path.getsize(temp_path)
            print(f"[CHECK] Upload anterior: {uploaded_size} bytes")
        
        return jsonify({'uploadedSize': uploaded_size, 'fileHash': file_hash})
        
    except Exception as e:
        print(f"[CHECK] ERRO: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/upload-chunk', methods=['POST'])
def upload_chunk():
    try:
        if 'chunk' not in request.files:
            return jsonify({'error': 'Chunk não encontrado'}), 400
        
        chunk = request.files['chunk']
        filename = secure_filename(request.form.get('filename'))
        file_hash = request.form.get('fileHash')
        chunk_start = int(request.form.get('chunkStart'))
        total_size = int(request.form.get('totalSize'))
        folder_id = request.form.get('folderId')
        
        folders = load_folders()
        if folder_id not in folders:
            return jsonify({'error': 'Pasta não encontrada'}), 404
        
        folder_path = folders[folder_id]['path']
        temp_path = os.path.join(app.config['TEMP_FOLDER'], file_hash)
        
        # Obtém ou cria lock para este arquivo
        with locks_lock:
            if file_hash not in file_locks:
                file_locks[file_hash] = threading.Lock()
            file_lock = file_locks[file_hash]
        
        # Usa lock para garantir escrita sequencial
        with file_lock:
            chunk_data = chunk.read()
            
            # Verifica tamanho atual
            current_size = 0
            if os.path.exists(temp_path):
                current_size = os.path.getsize(temp_path)
            
            # Se chunk_start é exatamente onde o arquivo termina, adiciona
            if chunk_start == current_size:
                with open(temp_path, 'ab') as f:
                    f.write(chunk_data)
            elif chunk_start < current_size:
                # Chunk já foi escrito, ignora
                print(f"[CHUNK] Chunk duplicado ignorado: {chunk_start}")
            else:
                # Há um buraco, espera chunks anteriores
                print(f"[CHUNK] AVISO: Aguardando chunks anteriores")
                return jsonify({
                    'status': 'waiting',
                    'progress': (current_size / total_size) * 100,
                    'uploadedSize': current_size
                })
            
            new_size = os.path.getsize(temp_path)
            progress = (new_size / total_size) * 100
            
            # Completo?
            if new_size >= total_size:
                final_path = os.path.join(folder_path, filename)
                
                # Se já existe, adiciona número
                base, ext = os.path.splitext(filename)
                counter = 1
                while os.path.exists(final_path):
                    final_path = os.path.join(folder_path, f"{base}_{counter}{ext}")
                    counter += 1
                
                os.rename(temp_path, final_path)
                
                # Remove lock
                with locks_lock:
                    if file_hash in file_locks:
                        del file_locks[file_hash]
                
                print(f"[CHUNK] ✓ COMPLETO: {final_path}")
                return jsonify({
                    'status': 'completed',
                    'progress': 100,
                    'message': 'Sucesso!',
                    'filename': os.path.basename(final_path)
                })
            
            return jsonify({
                'status': 'uploading',
                'progress': progress,
                'uploadedSize': new_size
            })
        
    except Exception as e:
        print(f"[CHUNK] ✗ ERRO: {e}")
        import traceback
        traceback.print_exc()
        return jsonify({'error': str(e)}), 500

@app.route('/cancel-upload', methods=['POST'])
def cancel_upload():
    try:
        data = request.get_json()
        file_hash = data.get('fileHash')
        
        if file_hash:
            temp_path = os.path.join(app.config['TEMP_FOLDER'], file_hash)
            if os.path.exists(temp_path):
                os.remove(temp_path)
                print(f"[CANCEL] Arquivo removido: {file_hash}")
        
        return jsonify({'status': 'cancelled'})
    except Exception as e:
        print(f"[CANCEL] ERRO: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/ping', methods=['GET', 'POST'])
def ping():
    """Teste de conectividade"""
    print("[PING] Recebido")
    return jsonify({'status': 'ok', 'message': 'pong'})

@app.route('/test-upload', methods=['POST'])
def test_upload():
    """Teste simples de upload"""
    try:
        print("[TEST] Recebendo teste de upload")
        
        if 'chunk' in request.files:
            chunk = request.files['chunk']
            data = chunk.read()
            print(f"[TEST] ✓ Chunk recebido: {len(data)} bytes")
            return jsonify({'status': 'ok', 'size': len(data)})
        else:
            print("[TEST] ✗ Nenhum chunk encontrado")
            return jsonify({'error': 'No chunk'}), 400
            
    except Exception as e:
        print(f"[TEST] ✗ ERRO: {e}")
        import traceback
        traceback.print_exc()
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    from werkzeug.serving import WSGIRequestHandler
    WSGIRequestHandler.protocol_version = "HTTP/1.1"
    
    app.run(
        host='0.0.0.0', 
        port=5000, 
        debug=True, 
        threaded=True,
        request_handler=WSGIRequestHandler
    )
