{% extends 'base.html' %}
{% block title %}上传数据 - 天璇{% endblock %}
{% block content %}
<style>
    #uploadCard { position: sticky; top: 1rem; z-index: 10; }
</style>
<div class="card" id="uploadCard">
    <h2>上传 CSV 文件</h2>
    <p style="color:#666;margin-bottom:1rem;">支持 .csv 文件，多文件批量上传，自动解压 .zip</p>
    <form id="uploadForm" enctype="multipart/form-data">
        {% csrf_token %}
            <div style="border:2px dashed #ccc;border-radius:8px;padding:2rem;text-align:center;background:#fafafa;" id="dropZone">
                <div style="font-size:2rem;margin-bottom:0.5rem;">📂</div>
                <p style="margin-bottom:1rem;color:#666;">拖拽 CSV 文件到此处</p>
                <input type="file" name="files" multiple accept=".csv,.zip" style="display:none;" id="fileInput">
                <button type="button" class="btn btn-primary" id="fileSelectBtn">📄 选择CSV文件</button>
            </div>
        <div id="submitBar" style="margin-top:1rem;display:none;">
            <button type="submit" class="btn btn-primary" id="submitBtn">开始上传</button>
        </div>
        <div id="progressArea" style="display:none;margin-top:1rem;">
            <p>上传中... <span id="progressText"></span></p>
            <div style="background:#eee;height:8px;border-radius:4px;overflow:hidden;">
                <div id="progressBar" style="background:#4361ee;height:100%;width:0%;"></div>
            </div>
        </div>
        <div id="fileList" style="margin-top:0.5rem;"></div>
    </form>
</div>

<div class="card" style="margin-top:1.5rem;">
    <h3>已上传的数据集</h3>
    {% if runs %}
    <table>
        <thead><tr><th>ID</th><th>文件</th><th>行数</th><th>状态</th><th>操作</th></tr></thead>
        <tbody>
            {% for run in runs %}
            <tr>
                <td>#{{ run.display_id }}</td>
                <td style="max-width:200px;overflow:hidden;text-overflow:ellipsis;">{% if run.sqlite_table %}SQLite表 {{ run.sqlite_table }}{% else %}{{ run.csv_glob }}{% endif %}</td>
                <td>{{ run.total_flows|default:"-" }}</td>
                <td><span class="badge {% if run.status == 'ready' or run.status == 'completed' %}badge-success{% elif run.status == 'failed' %}badge-danger{% else %}badge-warning{% endif %}">{{ run.status }}</span></td>
                <td>
                    {% if run.status == 'loading' or run.status == 'profiling' or run.status == 'aggregating' or run.status == 'clustering' or run.status == 'extracting' %}
                    <button class="btn btn-danger" style="background:#dc3545;color:#fff;padding:0.25rem 0.5rem;font-size:0.8rem;" onclick="deleteRun({{ run.display_id }}, true)">删除</button>
                    {% else %}
                    <button class="btn btn-danger" style="background:#dc3545;color:#fff;padding:0.25rem 0.5rem;font-size:0.8rem;" onclick="deleteRun({{ run.display_id }})">删除</button>
                    {% endif %}
                </td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
    {% else %}
    <p style="color:#999;">暂无已上传的数据集</p>
    {% endif %}
</div>

<script>
const dropZone = document.getElementById('dropZone');
const fileInput = document.getElementById('fileInput');
const fileList = document.getElementById('fileList');
const submitBar = document.getElementById('submitBar');
const submitBtn = document.getElementById('submitBtn');
let selectedFiles = [];

dropZone.addEventListener('dragover', e => { e.preventDefault(); dropZone.style.borderColor = '#4361ee'; });
dropZone.addEventListener('dragleave', () => dropZone.style.borderColor = '#ccc');
dropZone.addEventListener('drop', e => { e.preventDefault(); handleFiles(e.dataTransfer.files); });
document.getElementById('fileSelectBtn').addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', () => handleFiles(fileInput.files));

function handleFiles(files) {
    selectedFiles = [...files];
    renderFileList();
    submitBar.style.display = 'block';
}

function removeFile(index) {
    selectedFiles.splice(index, 1);
    renderFileList();
    submitBtn.disabled = false;
    if (selectedFiles.length === 0) submitBar.style.display = 'none';
}

function renderFileList() {
    fileList.innerHTML = selectedFiles.map((f, i) =>
        `<div style="padding:0.5rem;background:#f5f7fa;margin:0.25rem 0;border-radius:4px;display:flex;align-items:center;justify-content:space-between;">
            <span>${i+1}. ${f.name} (${(f.size/1024).toFixed(0)} KB)</span>
            <span onclick="removeFile(${i})" style="cursor:pointer;color:#dc3545;font-weight:bold;padding:0.1rem 0.4rem;border-radius:3px;user-select:none;">✕</span>
        </div>`
    ).join('');
}

document.getElementById('uploadForm').addEventListener('submit', async (e) => {
    e.preventDefault();
    const BATCH = 5;
    const batches = [];
    for (let i = 0; i < selectedFiles.length; i += BATCH) {
        batches.push(selectedFiles.slice(i, i + BATCH));
    }
    document.getElementById('progressArea').style.display = 'block';
    submitBtn.disabled = true;

    const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
    let runId = null;
    for (let bi = 0; bi < batches.length; bi++) {
        const form = new FormData();
        batches[bi].forEach(f => form.append('files', f));
        const url = runId ? `/upload/csv/batch/${runId}/` : '/upload/csv/';
        try {
            const resp = await fetch(url, { method: 'POST', body: form,
                headers: { 'X-CSRFToken': csrfToken } });
            const data = await resp.json();
            if (data.error) {
                document.getElementById('progressText').textContent = '上传失败: ' + data.error;
                submitBtn.disabled = false;
                return;
            }
            runId = runId || data.run_id;
            document.getElementById('progressBar').style.width = ((bi+1)/batches.length*100) + '%';
            document.getElementById('progressText').textContent = `上传批次 ${bi+1}/${batches.length} (run #${runId})`;
        } catch (err) {
            document.getElementById('progressText').textContent = '上传失败: ' + err.message;
            submitBtn.disabled = false;
            return;
        }
    }
    // All batches uploaded — finalize to trigger background processing
    document.getElementById('progressText').textContent = '正在初始化后台处理...';
    try {
        const finResp = await fetch(`/runs/${runId}/finalize/`, {
            method: 'POST',
            headers: { 'X-CSRFToken': csrfToken }
        });
        const finData = await finResp.json();
        if (finData.error) {
            document.getElementById('progressText').textContent = '初始化失败: ' + finData.error;
            submitBtn.disabled = false;
            return;
        }
    } catch (err) {
        document.getElementById('progressText').textContent = '初始化失败: ' + err.message;
        submitBtn.disabled = false;
        return;
    }
    // Upload complete — poll for background processing
    document.getElementById('progressText').textContent = '上传完成，后台处理中...';
    const poll = setInterval(async () => {
        try {
            const r = await fetch(`/runs/${runId}/status/`);
            const s = await r.json();
            const pct = s.progress_pct || 0;
            const msg = s.progress_msg || s.status;
            document.getElementById('progressBar').style.width = pct + '%';
            document.getElementById('progressText').textContent = `${msg} (${pct}%)`;
            if (s.status === 'ready' || s.status === 'completed') { clearInterval(poll); window.location.href = '/analyze/manual/?dataset=upload_' + runId; }
            if (s.status === 'failed') { clearInterval(poll); document.getElementById('progressText').textContent = '处理失败: ' + (s.error_message || '未知错误'); }
        } catch (e) { showError('轮询状态失败: ' + e.message); }
    }, 1000);
});

async function deleteRun(runId, processing) {
    const msg = processing ? '后台处理中，删除将中断分析，确认删除？' : '确定要删除此数据集吗？此操作不可撤销。';
    if (!confirm(msg)) return;
    try {
        let csrf = document.querySelector('[name=csrfmiddlewaretoken]');
        if (!csrf) {
            showError('页面已过期，请刷新后重试');
            return;
        }
        const resp = await fetch(`/runs/${runId}/delete/`, {
            method: 'POST',
            headers: { 'X-CSRFToken': csrf.value },
        });
        if (!resp.ok) {
            const text = await resp.text().catch(() => '');
            const snippet = text.length > 200 ? text.substring(0, 200) + '…' : text;
            showError('删除失败 (HTTP ' + resp.status + '): ' + (snippet || '服务器内部错误'));
            return;
        }
        const data = await resp.json();
        if (data.deleted) {
            showSuccess('已删除');
            location.reload();
        } else {
            showError('删除失败: 服务器返回了意外的响应');
        }
    } catch (err) {
        showError('删除失败: ' + err.message + ' — 请刷新页面后重试');
    }
}
</script>
{% endblock %}
