// import.jsx — PDF / Image import with direct Gemini API call (no serverless needed)

const { useState, useEffect, useCallback, useRef } = React;

const WORKER_SRC = 'https://unpkg.com/pdfjs-dist@3.11.174/build/pdf.worker.min.js';
// Gemini API — https://aistudio.google.com/app/apikey
// fallback list: ลองตัวแรกก่อน ถ้าไม่ได้ลองตัวถัดไป
const GEMINI_MODELS = [
  'gemini-2.0-flash',
  'gemini-2.5-flash-preview-05-20',
  'gemini-2.5-flash',
];

// ── API key helpers (stored in localStorage) ──────────────────
function getAIKey() {
  return localStorage.getItem('gemini_api_key') || '';
}
function saveAIKey(key) {
  localStorage.setItem('gemini_api_key', key.trim());
}

// ── Call Gemini API — ลอง fallback models อัตโนมัติ ──────────
async function callAI(messages) {
  const apiKey = getAIKey();
  if (!apiKey) throw new Error('ยังไม่ได้ตั้งค่า Gemini API Key — กดปุ่ม "แก้ไข" ด้านบน');
  const parts = (messages.content || []).map(c => {
    if (c.type === 'image_url') {
      const base64 = c.image_url.url.split(',')[1];
      return { inline_data: { mime_type: 'image/jpeg', data: base64 } };
    }
    return { text: c.text || c };
  });
  let lastErr = '';
  for (const model of GEMINI_MODELS) {
    const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`;
    let res;
    try {
      res = await fetch(url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          contents: [{ parts }],
          generationConfig: { temperature: 0.1, maxOutputTokens: 4096 },
        }),
      });
    } catch (e) {
      throw new Error('ไม่สามารถเชื่อมต่ออินเทอร์เน็ตได้: ' + e.message);
    }
    const data = await res.json();
    if (data.error) {
      const msg = data.error.message || '';
      // ถ้า model deprecated/ไม่รองรับ ลอง model ถัดไป
      if (msg.includes('no longer available') || msg.includes('not found') || msg.includes('deprecated')) {
        lastErr = `${model}: ${msg}`;
        continue;
      }
      throw new Error('Gemini: ' + msg);
    }
    return data.candidates?.[0]?.content?.parts?.[0]?.text || '';
  }
  throw new Error('ไม่พบ Gemini model ที่ใช้ได้: ' + lastErr);
}

// ── Compress image to JPEG base64 ─────────────────────────────
async function compressImageFile(file, maxPx = 1200) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const img = new Image();
      img.onload = () => {
        const scale = Math.min(1, maxPx / Math.max(img.width, img.height));
        const canvas = document.createElement('canvas');
        canvas.width  = Math.round(img.width  * scale);
        canvas.height = Math.round(img.height * scale);
        canvas.getContext('2d').drawImage(img, 0, 0, canvas.width, canvas.height);
        resolve(canvas.toDataURL('image/jpeg', 0.85));
      };
      img.onerror = reject;
      img.src = e.target.result;
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

// ── PDF: extract text + render each page as image ──────────
async function extractPDFPagesWithImages(file) {
  const lib = window.pdfjsLib;
  if (!lib) throw new Error('PDF.js ยังโหลดไม่เสร็จ');
  lib.GlobalWorkerOptions.workerSrc = WORKER_SRC;

  const buf = await file.arrayBuffer();
  const pdf = await lib.getDocument({ data: buf }).promise;
  const pages = [];

  for (let p = 1; p <= pdf.numPages; p++) {
    const page = await pdf.getPage(p);

    // --- extract text ---
    const content = await page.getTextContent();
    const text = content.items.map(i => i.str).join(' ');

    // --- render to canvas → JPEG base64 ---
    const viewport = page.getViewport({ scale: 1.8 });
    const canvas = document.createElement('canvas');
    canvas.width  = viewport.width;
    canvas.height = viewport.height;
    const ctx = canvas.getContext('2d');
    await page.render({ canvasContext: ctx, viewport }).promise;
    const imageDataUrl = canvas.toDataURL('image/jpeg', 0.82);

    pages.push({ text, imageDataUrl });
  }
  return pages;
}

// ── Robust JSON extractor (brace-balanced, not greedy regex) ─
function extractJSON(text) {
  for (const open of ['[', '{']) {
    const close = open === '[' ? ']' : '}';
    const start = text.indexOf(open);
    if (start === -1) continue;
    let depth = 0, inStr = false, esc = false;
    for (let i = start; i < text.length; i++) {
      const c = text[i];
      if (esc)      { esc = false; continue; }
      if (c === '\\' && inStr) { esc = true; continue; }
      if (c === '"') { inStr = !inStr; continue; }
      if (inStr)    continue;
      if (c === open)  depth++;
      if (c === close) { depth--; if (depth === 0) return text.slice(start, i + 1); }
    }
  }
  return null;
}

// ── AI parser — ส่งรูปทุกหน้าใน PDF ครั้งเดียว ────────────────
async function parseAllOrdersWithAI(pages, filename) {
  // pages = [{ text, imageDataUrl }, ...]
  const hint = filename.toLowerCase().includes('lazada') ? 'lazada'
    : filename.toLowerCase().includes('tiktok') ? 'tiktok'
    : filename.toLowerCase().includes('shopee') ? 'shopee' : '';

  // ตรวจว่า PDF มี text จริงไหม (บาง PDF เป็น image-based)
  const avgTextLen = pages.reduce((s, p) => s + (p.text || p || '').length, 0) / pages.length;
  const hasText = avgTextLen > 80;

  const instructText = `Parse ALL ${pages.length} Thai e-commerce shipping label pages. Return ONLY a valid JSON ARRAY, one object per page/label, no markdown.

Object schema (null for missing fields):
{
  "platform": "shopee"|"tiktok"|"lazada",
  "code": "order number",
  "date": "YYYY-MM-DD",
  "customer": "recipient name",
  "items": [{"name":"product","sku":"","qty":1}],
  "total_qty": number
}

Platform: SPX/Shopee→"shopee", TikTok Shop→"tiktok", Lazada/LEX→"lazada"${hint ? `, hint: "${hint}"` : ''}
Order number: look for "Order No.", "Order ID:", "เลขที่คำสั่งซื้อ", barcode numbers
Date priority (USE THE FIRST ONE FOUND):
  1. "PICKUP DATE" → use this date (most important)
  2. "PICK UP DATE" or "วันรับพัสดุ" → use this
  3. "SHIP BY DATE" → use this
  4. "วันที่จัดส่ง" or label print date → use this
  5. Last resort: date embedded in order number
Date format: "16-05-2026"→"2026-05-16", "11 May 2026"→"2026-05-11"
IMPORTANT: return EXACTLY ${pages.length} objects, one per page. Return [] only if truly no data.`;

  let raw;
  if (pages[0]?.imageDataUrl) {
    // Vision mode — ส่งรูปทุกหน้า + คำสั่ง
    const content = pages.map(p => ({
      type: 'image_url',
      image_url: { url: p.imageDataUrl.startsWith('data:') ? p.imageDataUrl : `data:image/jpeg;base64,${p.imageDataUrl}` },
    }));
    content.push({ type: 'text', text: instructText });
    raw = await callAI({ content, _vision: true });
  } else {
    // Text fallback
    const pageBlocks = pages.map((p, i) =>
      `=== หน้า ${i + 1} ===\n${(p.text || p || '').slice(0, 700)}`
    ).join('\n\n');
    raw = await callAI({ content: [{ type: 'text', text: instructText + '\n\nLABELS:\n' + pageBlocks }], _vision: false });
  }

  const jsonStr = extractJSON(raw);
  if (!jsonStr) throw new Error('AI ไม่สามารถแยกข้อมูลได้');
  const parsed = JSON.parse(jsonStr);
  return Array.isArray(parsed) ? parsed : [parsed];
}

// ── Process single image with Vision AI ───────────────────────
async function processImageWithAI(file) {
  const dataUrl = await compressImageFile(file, 1200);
  const base64 = dataUrl.split(',')[1];
  const hint = file.name.toLowerCase().includes('lazada') ? 'lazada'
    : file.name.toLowerCase().includes('tiktok') ? 'tiktok'
    : file.name.toLowerCase().includes('shopee') ? 'shopee' : '';
  const platformHint = hint ? `, hint: "${hint}"` : '';

  const text = await callAI({
    _vision: true,
    content: [
      { type: 'image_url', image_url: { url: `data:image/jpeg;base64,${base64}` } },
      { type: 'text', text: `Parse this Thai e-commerce shipping label image. Return ONLY a valid JSON ARRAY with one object per label, no markdown.

Object schema (null for missing):
{
  "platform": "shopee"|"tiktok"|"lazada",
  "code": "order number string",
  "date": "YYYY-MM-DD",
  "customer": "recipient name",
  "items": [{"name":"product name","sku":"","qty":1}],
  "total_qty": number
}

Platform: SPX/Shopee→"shopee", TikTok Shop→"tiktok", Lazada/LEX→"lazada"${platformHint}
Date priority (USE THE FIRST ONE FOUND):
  1. "PICKUP DATE" or "PICK UP DATE" → use this (most important)
  2. "SHIP BY DATE" → use this
  3. label print date or order date → use this
  4. Last resort: date from order number
Date format: "16-05-2026"→"2026-05-16", "11 May 2026"→"2026-05-11"
Return [] if no order data found. Only JSON array, no markdown.` },
    ],
  });

  const jsonStr = extractJSON(text);
  if (!jsonStr) throw new Error('AI ไม่สามารถแยกข้อมูลได้');
  const parsed = JSON.parse(jsonStr);
  const results = Array.isArray(parsed) ? parsed : [parsed];
  return { results, pageImages: [dataUrl] };
}

// ── helpers ───────────────────────────────────────────────────
function uid() { return 'imp-' + Math.random().toString(36).slice(2, 10); }

function fmtDateThai(iso) {
  if (!iso) return '-';
  const dt = new Date(iso + 'T00:00:00');
  const M = ['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.','ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'];
  return `${dt.getDate()} ${M[dt.getMonth()]} ${(dt.getFullYear()+543).toString().slice(-2)}`;
}

// ── API Key Banner (shown inside modal) ───────────────────────
function ApiKeyBanner({ onSaved }) {
  const [editing, setEditing] = useState(!getAIKey());
  const [val, setVal] = useState(getAIKey());
  const [saved, setSaved] = useState(false);

  const save = () => {
    saveAIKey(val);
    setSaved(true);
    setEditing(false);
    setTimeout(() => setSaved(false), 2000);
    if (onSaved) onSaved();
  };

  if (!editing) {
    const key = getAIKey();
    return (
      <div className="api-key-banner ok" onClick={() => { setVal(key); setEditing(true); }}>
        <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
          <circle cx="8" cy="8" r="6" stroke="currentColor" strokeWidth="1.3"/>
          <path d="M5.5 8l2 2 3-3" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round"/>
        </svg>
        {saved ? 'บันทึกแล้ว!' : <>Gemini API Key <span className="key-mask">••••{key.slice(-4)}</span> · <span className="key-edit-link">แก้ไข</span></>}
      </div>
    );
  }

  return (
    <div className="api-key-banner editing">
      <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
        <path d="M10 2a3 3 0 0 1 0 4.24L4.5 11.76 2 12l.24-2.5L7.76 4A3 3 0 0 1 10 2z"
          stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round"/>
      </svg>
      <input
        className="key-input"
        type="password"
        placeholder="วาง Gemini API Key (AIza...)"
        value={val}
        onChange={e => setVal(e.target.value)}
        onKeyDown={e => { if (e.key === 'Enter') save(); if (e.key === 'Escape') setEditing(false); }}
        autoFocus
      />
      <button className="key-save-btn" onClick={save} disabled={!val.trim()}>บันทึก</button>
      {getAIKey() && <button className="key-cancel-btn" onClick={() => setEditing(false)}>ยกเลิก</button>}
    </div>
  );
}

// ── DropZone ──────────────────────────────────────────────────
function DropZone({ onFiles, disabled }) {
  const [drag, setDrag] = useState(false);
  const inp = useRef(null);

  const pick = (files) => {
    const valid = [...files].filter(f =>
      f.type === 'application/pdf' || f.name.endsWith('.pdf') || f.type.startsWith('image/')
    );
    if (valid.length) onFiles(valid);
  };

  return (
    <div
      className={`drop-zone ${drag ? 'dragging' : ''} ${disabled ? 'disabled' : ''}`}
      onDragOver={(e) => { e.preventDefault(); if (!disabled) setDrag(true); }}
      onDragLeave={() => setDrag(false)}
      onDrop={(e) => { e.preventDefault(); setDrag(false); if (!disabled) pick(e.dataTransfer.files); }}
      onClick={() => !disabled && inp.current?.click()}
    >
      <input ref={inp} type="file" accept=".pdf,application/pdf,image/*" multiple
        style={{ display: 'none' }} onChange={(e) => pick(e.target.files)} />
      <div className="dz-icon">
        <svg width="36" height="36" viewBox="0 0 36 36" fill="none">
          <rect x="4" y="4" width="28" height="28" rx="6" stroke="currentColor" strokeWidth="1.5" strokeDasharray="4 3"/>
          <path d="M18 24V14M13 19l5-5 5 5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
        </svg>
      </div>
      <p className="dz-title">ลากไฟล์วางที่นี่</p>
      <p className="dz-sub">PDF · JPG · PNG · รองรับหลายไฟล์พร้อมกัน</p>
      <div className="dz-platforms">
        {['shopee','tiktok','lazada'].map(pid => {
          const p = PLATFORMS[pid];
          return (
            <span key={pid} className="dz-platform-chip" style={{ borderColor: p.dot, color: p.dot }}>
              <span className="platform-badge" style={{ width:14, height:14, background: p.dot, fontSize:7, borderRadius:3 }}>{p.short}</span>
              {p.name}
            </span>
          );
        })}
      </div>
    </div>
  );
}

// ── File processing row ────────────────────────────────────────
function FileRow({ entry, onRemove }) {
  const { file, state, results = [], error } = entry;

  return (
    <div className={`import-file-row state-${state}`}>
      <div className="ifr-left">
        <div className="ifr-icon">
          <svg width="16" height="16" viewBox="0 0 20 20" fill="none">
            <path d="M5 2h7l5 5v11a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1z"
              stroke="currentColor" strokeWidth="1.2"/>
            <path d="M12 2v5h5" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round"/>
            <path d="M7 13h6M7 10h4" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round"/>
          </svg>
        </div>
        <div className="ifr-info">
          <div className="ifr-name">{file.name}</div>
          {state === 'loading' && (
            <div className="ifr-status">
              <span className="dots-anim">กำลังอ่านไฟล์และวิเคราะห์ด้วย AI</span>
            </div>
          )}
          {state === 'error' && (
            <div className="ifr-status error">{error}</div>
          )}
          {state === 'done' && results.length > 0 && (
            <div className="ifr-result">
              <span className="ifr-qty">{results.length} คำสั่งซื้อ</span>
              <span className="dot-sep">·</span>
              {results.slice(0, 3).map((r, i) => {
                const p2 = PLATFORMS[r.platform];
                return p2 ? (
                  <span key={i} className="platform-badge" style={{ width:16, height:16, background: p2.dot, fontSize:8, borderRadius:3 }}>{p2.short}</span>
                ) : null;
              })}
              {results.length > 3 && <span style={{fontSize:11,color:'var(--ink-3)'}}>+{results.length - 3}</span>}
            </div>
          )}
        </div>
      </div>
      <div className="ifr-right">
        {state === 'loading' && <div className="import-spinner" />}
        {state === 'done' && <span className="ifr-ok">✓</span>}
        {state === 'error' && <span className="ifr-err">!</span>}
        <button className="ifr-remove" onClick={() => onRemove(file.name)}>×</button>
      </div>
    </div>
  );
}

// ── Review list ────────────────────────────────────────────────
function ReviewList({ results, onRemove }) {
  return (
    <div className="review-list">
      {results.map((r, i) => {
        const p = PLATFORMS[r.platform] || PLATFORMS.shopee;
        return (
          <div key={i} className="review-card">
            <div className="rc-header">
              <span className="platform-badge" style={{ width:20, height:20, background: p.dot, fontSize:9, borderRadius:4 }}>{p.short}</span>
              <span className="rc-platform">{p.name}</span>
              <span className="rc-code">{r.code || 'ไม่พบเลข'}</span>
              <span className="dot-sep">·</span>
              <span className="rc-customer">{r.customer || '-'}</span>
              <span className="dot-sep">·</span>
              <span>{fmtDateThai(r.date)}</span>
              <div style={{flex:1}} />
              <span className="rc-qty-badge">{r.total_qty || 0} ชิ้น</span>
              <button className="rc-remove" onClick={() => onRemove(i)} title="เอาออก">×</button>
            </div>
            {r.items && r.items.length > 0 && (
              <div className="rc-items">
                {r.items.map((item, j) => (
                  <div key={j} className="rc-item">
                    <span className="rci-name">{item.name}</span>
                    {item.sku && <span className="rci-sku">{item.sku}</span>}
                    <span className="rci-qty">×{item.qty}</span>
                  </div>
                ))}
              </div>
            )}
          </div>
        );
      })}
    </div>
  );
}

// ── Main ImportModal ───────────────────────────────────────────
function ImportModal({ onClose, onImport }) {
  const [entries, setEntries] = useState([]);
  const [step, setStep] = useState('upload');
  const [reviewItems, setReviewItems] = useState([]);
  const [keySet, setKeySet] = useState(!!getAIKey());
  const processingRef = useRef(new Set());

  useEffect(() => {
    const fn = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', fn);
    return () => window.removeEventListener('keydown', fn);
  }, [onClose]);

  const handleFiles = useCallback(async (files) => {
    if (!getAIKey()) return;
    const accepted = [...files].filter(f =>
      f.type === 'application/pdf' || f.name.endsWith('.pdf') || f.type.startsWith('image/')
    );
    const newFiles = accepted.filter(f => !processingRef.current.has(f.name));
    if (!newFiles.length) return;

    newFiles.forEach(f => processingRef.current.add(f.name));
    setEntries(prev => [
      ...prev,
      ...newFiles.map(f => ({ file: f, state: 'loading', results: [], error: null }))
    ]);

    for (const f of newFiles) {
      try {
        let results, pageImages;
        const isPDF = f.type === 'application/pdf' || f.name.endsWith('.pdf');
        if (isPDF) {
          const pages = await extractPDFPagesWithImages(f);
          pageImages = pages.map(p => p.imageDataUrl);
          results = await parseAllOrdersWithAI(pages, f.name);
        } else {
          const out = await processImageWithAI(f);
          results = out.results;
          pageImages = out.pageImages;
        }
        setEntries(prev => prev.map(e =>
          e.file.name === f.name ? { ...e, state: 'done', results, pageImages } : e
        ));
      } catch (err) {
        setEntries(prev => prev.map(e =>
          e.file.name === f.name ? { ...e, state: 'error', error: err.message } : e
        ));
      }
    }
  }, []);

  const removeEntry = (name) => {
    setEntries(prev => prev.filter(e => e.file.name !== name));
    processingRef.current.delete(name);
  };

  const doneResults = entries.filter(e => e.state === 'done').flatMap(e => {
    const imgs = e.pageImages || [];
    return (e.results || []).map((r, i) => ({ ...r, _pageImage: imgs[i] || null }));
  });
  const allSettled = entries.length > 0 && entries.every(e => e.state === 'done' || e.state === 'error');
  const isLoading = entries.some(e => e.state === 'loading');

  const goReview = () => { setReviewItems([...doneResults]); setStep('review'); };
  const removeReview = (i) => setReviewItems(prev => prev.filter((_, j) => j !== i));

  const doImport = () => {
    const orders = reviewItems
      .filter(r => r?.platform && r?.code)
      .map(r => ({
        id: uid(),
        platform: r.platform,
        code: r.code,
        date: r.date || new Date().toISOString().slice(0, 10),
        qty: r.total_qty || (r.items || []).reduce((s, it) => s + (it.qty || 0), 0) || 1,
        customer: r.customer || '',
        status: 'pending',
        tags: [],
        note: '',
        items: r.items || [],
        images: r._pageImage ? [{ id: 'pdf-' + Math.random().toString(36).slice(2,8), dataUrl: r._pageImage }] : [],
        updated: Date.now(),
      }));
    onImport(orders);
    onClose();
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal import-modal" onClick={e => e.stopPropagation()}>

        <header className="modal-header">
          <div>
            <div className="modal-eyebrow">
              <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
                <path d="M8 2v8M4 7l4 4 4-4M3 13h10"
                  stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/>
              </svg>
              <span>นำเข้าข้อมูลคำสั่งซื้อ</span>
            </div>
            <h2 className="modal-title">อัปโหลดไฟล์ PDF หรือรูปภาพ</h2>
          </div>
          <button className="close-btn" onClick={onClose}>×</button>
        </header>

        <div className="modal-body">
          <ApiKeyBanner onSaved={() => setKeySet(true)} />

          {step === 'upload' && (
            <>
              <DropZone onFiles={handleFiles} disabled={isLoading || !keySet} />
              {!keySet && (
                <p style={{fontSize:12,color:'var(--ink-3)',textAlign:'center',marginTop:8}}>
                  ตั้งค่า API Key ด้านบนก่อนเพื่อเปิดใช้งาน
                </p>
              )}
              {entries.length > 0 && (
                <div className="import-file-list">
                  {entries.map(entry => (
                    <FileRow key={entry.file.name} entry={entry} onRemove={removeEntry} />
                  ))}
                </div>
              )}
              {isLoading && (
                <div className="import-ai-note">
                  <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
                    <circle cx="8" cy="8" r="6" stroke="currentColor" strokeWidth="1.3"/>
                    <path d="M8 5v3l2 2" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round"/>
                  </svg>
                  AI กำลังวิเคราะห์ข้อมูล — อาจใช้เวลาสักครู่
                </div>
              )}
            </>
          )}

          {step === 'review' && (
            <div>
              <p className="review-desc">
                ตรวจสอบข้อมูลก่อนนำเข้า — กด × เพื่อเอาออก · ข้อมูลถูกต้องแล้วกด "นำเข้า"
              </p>
              {reviewItems.length === 0
                ? <div className="empty-state" style={{padding:'24px 0'}}>ไม่มีข้อมูลที่จะนำเข้า</div>
                : <ReviewList results={reviewItems} onRemove={removeReview} />
              }
            </div>
          )}
        </div>

        <footer className="modal-footer">
          {step === 'upload' ? (
            <>
              <button className="btn ghost" onClick={onClose}>ยกเลิก</button>
              <button className="btn primary"
                disabled={!allSettled || doneResults.length === 0}
                onClick={goReview}
              >
                ตรวจสอบข้อมูล
                {doneResults.length > 0 && ` (${doneResults.length})`}
              </button>
            </>
          ) : (
            <>
              <button className="btn ghost" onClick={() => setStep('upload')}>← กลับแก้ไข</button>
              <button className="btn primary"
                disabled={reviewItems.length === 0}
                onClick={doImport}
              >
                นำเข้า {reviewItems.length} คำสั่งซื้อ
              </button>
            </>
          )}
        </footer>

      </div>
    </div>
  );
}

Object.assign(window, { ImportModal });
