let sessionId = null;
const pdfFiles = [], imgFiles = [];
let invoiceData = [];   // 当前编辑数据 [{__row, ...fields}]
let csvFilename = '';    // 当前 CSV 文件名
let lastDownloadUrls = {};  // 最近一次可下载文件链接

// ---- Session ----
async function ensureSession() {
  if (sessionId) return sessionId;
  const r = await fetch('/api/session', { method: 'POST' });
  const d = await r.json();
  sessionId = d.session_id;
  return sessionId;
}

// ---- 上传 ----
function handleFiles(input, type) {
  const files = Array.from(input.files);
  const list = type === 'pdf' ? pdfFiles : imgFiles;
  const listId = type === 'pdf' ? 'pdf-list' : 'img-list';
  const zoneId = type === 'pdf' ? 'pdf-zone' : 'img-zone';

  files.forEach(f => {
    if (!list.find(x => x.name === f.name)) {
      f.__source = 'local';  // 标记为本地手动选择
      list.push(f);
    }
  });

  renderFileList(type);
  document.getElementById(zoneId).classList.add('active');
  input.value = '';
}

function removeFile(type, index) {
  const list = type === 'pdf' ? pdfFiles : imgFiles;
  list.splice(index, 1);
  renderFileList(type);
  if (list.length === 0) {
    document.getElementById(type === 'pdf' ? 'pdf-zone' : 'img-zone').classList.remove('active');
  }
}

function renderFileList(type) {
  const list = type === 'pdf' ? pdfFiles : imgFiles;
  const box = document.getElementById(type === 'pdf' ? 'pdf-list' : 'img-list');
  box.innerHTML = list.map((f, i) =>
    `<span class="file-tag">${f.name}<span class="remove" onclick="event.stopPropagation();removeFile('${type}',${i})">&times;</span></span>`
  ).join('');
}

// ---- 配置上传 ----
function handleConfigUpload(input) {
  const file = input.files[0];
  if (!file) return;
  const reader = new FileReader();
  reader.onload = function(e) {
    try {
      const cfg = JSON.parse(e.target.result);
      const map = {
        'cfg-username': cfg.username,
        'cfg-password': cfg.password,
        'cfg-name': cfg.default_name,
        'cfg-card': cfg.default_card_no,
        'cfg-person-id': cfg.default_person_id,
        'cfg-storage': cfg.consumable_storage,
      };
      for (const [id, val] of Object.entries(map)) {
        if (val) document.getElementById(id).value = val;
      }
      // 同步 config.json 中的工号和公务卡号到表格
      if (cfg.username) syncConfigToTable('工号');
      if (cfg.default_card_no) syncConfigToTable('公务卡号');
      alert('配置已加载');
    } catch (err) {
      alert('config.json 解析失败: ' + err.message);
    }
  };
  reader.readAsText(file);
  input.value = '';
}

// ---- 拖拽 ----
['pdf','img'].forEach(type => {
  const zone = document.getElementById(type + '-zone');
  zone.addEventListener('dragover', e => { e.preventDefault(); zone.classList.add('dragover'); });
  zone.addEventListener('dragleave', () => zone.classList.remove('dragover'));
  zone.addEventListener('drop', e => {
    e.preventDefault();
    zone.classList.remove('dragover');
    const files = Array.from(e.dataTransfer.files).filter(f => {
      if (type === 'pdf') return f.name.toLowerCase().endsWith('.pdf');
      /\.(png|jpe?g|bmp|webp)$/i.test(f.name);
    });
    if (files.length) {
      const list = type === 'pdf' ? pdfFiles : imgFiles;
      files.forEach(f => {
        f.__source = 'local';  // 标记为本地拖拽
        if (!list.find(x => x.name === f.name)) list.push(f);
      });
      renderFileList(type);
      zone.classList.add('active');
    }
  });
});

// ---- 处理 ----
async function startProcess() {
  if (!pdfFiles.length && !imgFiles.length) {
    alert('请先上传文件或图片');
    return;
  }

  const btn = document.getElementById('btn-start');
  btn.disabled = true;
  btn.textContent = '处理中...';
  document.getElementById('status').innerHTML = '<span class="badge bg-warning status-badge">上传中...</span>';
  document.getElementById('log-box').innerHTML = '';
  document.getElementById('edit-section').style.display = 'none';
  document.getElementById('download-section').style.display = 'none';

  try {
    await ensureSession();

    const allFiles = [...pdfFiles.map(f => ({f, t:'pdf'})), ...imgFiles.map(f => ({f, t:'img'}))];
    for (const {f} of allFiles) {
      const fd = new FormData();
      fd.append('file', f);
      await fetch(`/api/upload/${sessionId}`, { method: 'POST', body: fd });
    }

    document.getElementById('status').innerHTML = '<span class="badge bg-info status-badge">处理中...</span>';

    const cfg = {
      username: document.getElementById('cfg-username').value,
      password: document.getElementById('cfg-password').value,
      default_name: document.getElementById('cfg-name').value,
      default_card_no: document.getElementById('cfg-card').value,
      default_person_id: document.getElementById('cfg-person-id').value,
      consumable_storage: document.getElementById('cfg-storage').value,
    };

    await fetch(`/api/process/${sessionId}`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(cfg),
    });

    // 监听 SSE 日志
    const es = new EventSource(`/api/logs/${sessionId}`);
    const logBox = document.getElementById('log-box');
    let firstLine = true;

    es.addEventListener('message', e => {
      if (firstLine) { logBox.innerHTML = ''; firstLine = false; }
      try {
        const msg = JSON.parse(e.data);
        if (msg.type === 'done') {
          es.close();
          const result = msg.result;
          document.getElementById('status').innerHTML = result.ok
            ? '<span class="badge bg-success status-badge">完成</span>'
            : '<span class="badge bg-danger status-badge">失败</span>';
          btn.disabled = false;
          btn.textContent = '开始处理';

          if (result.ok) {
            showDownloadLinks(result);
            loadInvoiceData();  // 加载可编辑数据
          } else {
            alert('处理失败: ' + (result.error || '未知错误'));
          }
          return;
        }
      } catch (err) {}
      logBox.innerHTML += e.data;
      logBox.scrollTop = logBox.scrollHeight;
    });

    es.onerror = () => {
      es.close();
      document.getElementById('status').innerHTML = '<span class="badge bg-danger status-badge">连接中断</span>';
      btn.disabled = false;
      btn.textContent = '开始处理';
    };

  } catch (e) {
    alert('请求失败: ' + (e.message || '未知错误'));
    btn.disabled = false;
    btn.textContent = '开始处理';
    document.getElementById('status').innerHTML = '<span class="badge bg-danger status-badge">失败</span>';
  }
}

// ---- 下载链接 ----
function showDownloadLinks(result) {
  const section = document.getElementById('download-section');
  const box = document.getElementById('download-links');
  const warn = document.getElementById('doc-fill-warning');
  if (!section || !box) return;

  const items = [];
  if (result.csv_url) items.push({ label: 'invoice_summary.csv', url: result.csv_url });
  if (result.doc_url) items.push({ label: '易耗品、出库单.doc', url: result.doc_url });

  lastDownloadUrls = {};
  items.forEach(it => { lastDownloadUrls[it.label] = it.url; });

  box.innerHTML = items.map(it =>
    `<a class="btn btn-outline-primary btn-sm" href="${it.url}" download>${it.label}</a>`
  ).join('');

  if (warn) {
    if (result.doc_skipped) {
      warn.style.display = 'block';
      warn.style.color = '#0d6efd';
      warn.textContent = result.doc_message || '差旅报销无需生成易耗品出库单';
    } else if (result.doc_ok === false && result.doc_error) {
      warn.style.display = 'block';
      warn.style.color = '';
      warn.textContent = '出库单未生成：' + result.doc_error;
    } else {
      warn.style.display = 'none';
      warn.textContent = '';
    }
  }

  section.style.display = items.length || (result.doc_ok === false) || result.doc_skipped ? 'block' : 'none';
}

// ---- 发票数据编辑 ----
async function loadInvoiceData() {
  try {
    const r = await fetch(`/api/data/${sessionId}`);
    const d = await r.json();
    if (d.error) return;

    csvFilename = d.csv_filename || 'invoice_summary.csv';
    invoiceData = d.data || [];
    const fields = d.fields || Object.keys(invoiceData[0] || {}).filter(k => !k.startsWith('__'));
    renderTable(invoiceData, fields);

    // 渲染后自动将配置区的工号/公务卡号同步到表格
    syncConfigToTable('工号');
    syncConfigToTable('公务卡号');
  } catch (e) { /* ignore */ }
}

// 配置区 → 表格的同步映射：工号 ↔ cfg-username，公务卡号 ↔ cfg-card
const CONFIG_SYNC = {
  '工号': 'cfg-username',
  '公务卡号': 'cfg-card',
};

// 从配置区输入框的值更新到所有表格行
function syncConfigToTable(field) {
  const inputId = CONFIG_SYNC[field];
  if (!inputId) return;
  const val = document.getElementById(inputId).value || '';
  invoiceData.forEach((row, i) => {
    row[field] = val;
  });
  // 更新表格中对应单元格的显示
  const tbody = document.getElementById('invoice-tbody');
  if (!tbody) return;
  const rows = tbody.querySelectorAll('tr');
  rows.forEach((tr, i) => {
    const inputs = tr.querySelectorAll('input');
    fieldsCache.forEach((f, colIdx) => {
      if (f === field && inputs[colIdx]) {
        inputs[colIdx].value = val;
      }
    });
  });
}

let fieldsCache = []; // renderTable 渲染后的字段列表，用于定位列索引

function renderTable(data, fields) {
  const section = document.getElementById('edit-section');
  if (!data.length) { section.style.display = 'none'; return; }
  section.style.display = 'block';

  // 使用后端返回的字段顺序， fallback 到 Object.keys
  if (!fields || !fields.length) {
    fields = Object.keys(data[0]).filter(k => !k.startsWith('__'));
  }
  fieldsCache = fields;

  // 表头
  document.getElementById('invoice-thead').innerHTML = `
    <tr>
      <th style="width:40px">#</th>
      ${fields.map(f => `<th>${f}</th>`).join('')}
    </tr>
  `;

  // 表体：每行首列为序号，其后为各字段 input
  const rows = data.map((row, i) => {
    const cells = fields.map(f => {
      let onChangeStr = `invoiceData[${i}]['${f.replace(/'/g, "\\'")}']=this.value`;
      // 如果该字段参与配置区同步，额外调用 syncTableToConfig
      if (CONFIG_SYNC[f]) {
        onChangeStr += `;syncTableToConfig('${f.replace(/'/g, "\\'")}', this.value)`;
      }
      return `<td><input class="form-control form-control-sm" value="${escapeHtml(String(row[f] || ''))}" 
        onchange="${onChangeStr}"></td>`;
    }).join('');
    return `<tr><td style="width:40px;text-align:center">${i + 1}</td>${cells}</tr>`;
  }).join('');

  document.getElementById('invoice-tbody').innerHTML = rows;
}

// 从表格修改同步回配置区
function syncTableToConfig(field, value) {
  const inputId = CONFIG_SYNC[field];
  if (inputId) {
    document.getElementById(inputId).value = value;
  }
}

function escapeHtml(s) {
  return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
}

// 将当前表格编辑内容写回服务器（内部调用）
async function saveInvoiceData() {
  try {
    const r = await fetch(`/api/save/${sessionId}`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ data: invoiceData, csv_filename: csvFilename }),
    });
    const d = await r.json();
    if (d.doc_url || d.doc_ok === false) {
      showDownloadLinks({
        csv_url: lastDownloadUrls['invoice_summary.csv'],
        doc_url: d.doc_url,
        doc_ok: d.doc_ok,
        doc_error: d.doc_error,
      });
    }
  } catch (e) {
    console.warn('自动保存失败，继续提交:', e);
  }
}

// ---- 提交到财务系统 ----
async function submitFinancial() {
  const btn = document.getElementById('btn-submit');
  btn.disabled = true;
  btn.textContent = '提交中...';
  document.getElementById('log-box').innerHTML = '';

  try {
    // 提交前先自动保存当前表格编辑内容
    await saveInvoiceData();

    await fetch(`/api/submit-financial/${sessionId}`, { method: 'POST' });

    // 监听日志流（复用 SSE）
    const es = new EventSource(`/api/logs/${sessionId}`);
    const logBox = document.getElementById('log-box');
    let firstLine = true;

    es.addEventListener('message', e => {
      if (firstLine) { logBox.innerHTML = ''; firstLine = false; }
      try {
        const msg = JSON.parse(e.data);
        if (msg.type === 'done') {
          es.close();
          btn.disabled = false;
          const result = msg.result;
          if (result && result.submit_ok) {
            btn.textContent = '✅ 提交完成';
            setTimeout(() => { btn.textContent = '🚀 提交到财务系统'; }, 3000);
          } else {
            const errorMsg = result?.submit_error || result?.error || '未知错误';
            btn.textContent = '❌ 提交失败';
            logBox.innerHTML += `<div style="color: #e74c3c; font-weight: bold;">❌ 提交失败：${errorMsg}</div>`;
            logBox.scrollTop = logBox.scrollHeight;
            console.warn('提交失败:', errorMsg);
            setTimeout(() => { btn.textContent = '🚀 提交到财务系统'; }, 5000);
          }
          return;
        }
      } catch (err) {}
      logBox.innerHTML += e.data;
      logBox.scrollTop = logBox.scrollHeight;
    });

    es.onerror = () => {
      es.close();
      btn.disabled = false;
      btn.textContent = '🚀 提交到财务系统';
    };
  } catch (e) {
    alert('提交失败: ' + e.message);
    btn.disabled = false;
    btn.textContent = '🚀 提交到财务系统';
  }
}

// ---- 二维码 / 手机扫码上传 ----
let qrGenerated = false;
let syncTimer = null;

async function generateQr() {
  await ensureSession();
  const mobileUrl = window.location.origin + '/mobile/' + sessionId;
  const box = document.getElementById('qrcode');
  box.innerHTML = '';
  new QRCode(box, {
    text: mobileUrl,
    width: 120,
    height: 120,
    colorDark: '#333',
    colorLight: '#fff',
  });
  qrGenerated = true;
}

// ---- 实时同步：轮询服务器文件列表，检测手机端上传的新图片 ----
async function startSync() {
  if (syncTimer) return;
  await syncFiles();
  syncTimer = setInterval(syncFiles, 3000);
}

function stopSync() {
  if (syncTimer) { clearInterval(syncTimer); syncTimer = null; }
}

async function syncFiles() {
  if (!sessionId) return;
  try {
    const r = await fetch(`/api/files/${sessionId}`);
    const d = await r.json();
    const serverNames = new Set(d.images || []);
    const localNames = new Set(imgFiles.map(f => f.name));

    for (const name of serverNames) {
      if (!localNames.has(name)) {
        const resp = await fetch(`/api/download/${sessionId}/${encodeURIComponent(name)}`);
        const blob = await resp.blob();
        const file = new File([blob], name, { type: blob.type });
        file.__source = 'server';  // 标记为扫码上传
        imgFiles.push(file);
      }
    }

    // 只清理来自服务器但已不存在的文件，保留本地手动选择的文件
    for (const f of [...imgFiles]) {
      if (!serverNames.has(f.name) && f.__source !== 'local') {
        const idx = imgFiles.indexOf(f);
        if (idx > -1) imgFiles.splice(idx, 1);
      }
    }

    renderFileList('img');
    if (imgFiles.length) {
      document.getElementById('img-zone').classList.add('active');
    } else {
      document.getElementById('img-zone').classList.remove('active');
    }
  } catch (e) { /* ignore */ }
}

generateQr();
startSync();

// ---- 配置区 → 表格的双向同步绑定 ----
Object.values(CONFIG_SYNC).forEach(inputId => {
  const el = document.getElementById(inputId);
  if (el) {
    el.addEventListener('input', () => {
      // 根据 inputId 反查对应的字段名
      const field = Object.entries(CONFIG_SYNC).find(([, id]) => id === inputId)?.[0];
      if (field) syncConfigToTable(field);
    });
  }
});