import { useState, useRef, useEffect } from 'react'

export default function App() {
  const [tab, setTab] = useState('local')   // 'local' | 'drive'
  const [files, setFiles] = useState([])
  const [driveUrl, setDriveUrl] = useState('')
  const [isDragging, setIsDragging] = useState(false)
  const [isLoading, setIsLoading] = useState(false)
  const [error, setError] = useState(null)
  
  // Results
  const [jobId, setJobId] = useState(null)
  const [stats, setStats] = useState(null)

  const [driveApiReady, setDriveApiReady] = useState(null)
  const fileInputRef = useRef(null)
  const folderInputRef = useRef(null)

  const [params, setParams] = useState({
    ppm: 15, sn: 1.5, min_pw: 5, max_pw: 20, pref_k: 0, pref_i: 0
  })

  useEffect(() => {
    if (tab === 'drive' && driveApiReady === null) {
      fetch('/api/gdrive-status')
        .then(r => r.json())
        .then(d => setDriveApiReady(d.configured))
        .catch(() => setDriveApiReady(false))
    }
  }, [tab, driveApiReady])

  // ── Handlers ─────────────────────────────────────────────────────────────
  const validateAndAdd = (selected) => {
    setError(null)
    setJobId(null)
    const valid = Array.from(selected).filter(f => {
      const n = f.name.toLowerCase()
      return n.endsWith('.mzml') || n.endsWith('.mzxml')
    })
    const skipped = Array.from(selected).length - valid.length
    if (skipped > 0) setError(`${skipped} file(s) skipped — only .mzML / .mzXML allowed.`)
    if (valid.length > 0) setFiles(prev => {
      const existing = new Set(prev.map(f => f.name))
      return [...prev, ...valid.filter(f => !existing.has(f.name))]
    })
  }
  const clearAll = () => { setFiles([]); setJobId(null); setError(null) }
  const handleParamChange = (e) => {
    const { name, value } = e.target
    setParams(p => ({ ...p, [name]: value }))
  }

  // Drag & drop
  const onDragOver = e => { e.preventDefault(); setIsDragging(true) }
  const onDragLeave = e => { e.preventDefault(); setIsDragging(false) }
  const onDrop = e => { e.preventDefault(); setIsDragging(false); validateAndAdd(e.dataTransfer.files) }

  // ── Submission ──────────────────────────────────────────────────────────
  const startJob = async () => {
    if (tab === 'local' && files.length === 0) { setError('Please select files first.'); return }
    if (tab === 'drive' && !driveUrl.trim()) { setError('Please enter a Drive folder URL.'); return }
    
    setIsLoading(true); setError(null); setJobId(null)

    try {
      let response;
      if (tab === 'local') {
        const formData = new FormData()
        files.forEach(f => formData.append('files', f))
        Object.keys(params).forEach(k => formData.append(k, params[k]))
        
        response = await fetch('/api/peak-picker/batch', { method: 'POST', body: formData })
      } else {
        response = await fetch('/api/peak-picker/gdrive', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ folderUrl: driveUrl, ...params }),
        })
      }

      const data = await response.json();
      if (!response.ok) throw new Error(data.error || 'Processing failed')
      
      setJobId(data.jobId)
      setStats({
        totalFiles: data.total,
        successFiles: data.count,
        errors: data.errors || []
      })

    } catch (err) {
      setError(err.message)
    } finally {
      setIsLoading(false)
    }
  }

  // ── Render ──────────────────────────────────────────────────────────────
  const totalFiles = files.length;

  return (
    <div className="page">
      <header>
        <div className="title-block">
          <h1>Metabol<span>ID</span></h1>
          <p>LC-MS Batch Peak Picker · XCMS CentWave Engine</p>
        </div>
        <div className="header-meta">
          A*STAR Bioinformatics Institute<br/>
          Free for academic use<br/>
          <span style={{fontSize: '10px'}}>© 2026 A*STAR · Commercial licensing: <a href="mailto:yeohc@a-star.edu.sg" style={{color: 'var(--ink2)'}}>yeohc@a-star.edu.sg</a></span>
        </div>
      </header>

      <div className="layout">
        <div className="main-col">
          
          <div className="section-label">01 · Input</div>
          <div className="card">
            <div className="mode-tabs">
              <button className={`tab-btn ${tab === 'local' ? 'active' : ''}`} onClick={() => {setTab('local'); setError(null)}}>
                <strong>📁 Upload Files / Folder</strong>
                Select multiple .mzML/.mzXML files<br/>or an entire directory
              </button>
              <button className={`tab-btn ${tab === 'drive' ? 'active' : ''}`} onClick={() => {setTab('drive'); setError(null)}}>
                <strong>☁ Google Drive Folder</strong>
                Paste a shared folder link<br/>Any size · No upload limit
              </button>
            </div>

            {/* Local Panel */}
            {tab === 'local' && (
              <div className="input-panel active">
                <div 
                  className={`drop-zone ${isDragging ? 'drag-active' : ''}`}
                  onDragOver={onDragOver} onDragLeave={onDragLeave} onDrop={onDrop}
                >
                  <input type="file" ref={fileInputRef} onChange={e => validateAndAdd(e.target.files)} accept=".mzml,.mzxml" multiple style={{ display: 'none' }} />
                  <input type="file" ref={folderInputRef} onChange={e => validateAndAdd(e.target.files)} accept=".mzml,.mzxml" webkitdirectory="" mozdirectory="" style={{ display: 'none' }} />
                  
                  <div className="drop-icon">📂</div>
                  <div className="drop-text">
                    {totalFiles === 0 ? (
                      <><strong>Drop your files here</strong><br/>or use the buttons below to browse</>
                    ) : (
                      <><strong>{totalFiles} file{totalFiles > 1 ? 's' : ''} selected</strong><br/>Drop more to add</>
                    )}
                  </div>
                  {totalFiles > 0 && (
                    <div className="file-chosen">
                      ✓ Ready to process {(files.reduce((acc, f) => acc + f.size, 0) / 1024 / 1024).toFixed(1)} MB
                    </div>
                  )}
                </div>

                <div style={{ display: 'flex', gap: '0.5rem', marginTop: '1rem', justifyContent: 'center' }}>
                  <button className="btn-secondary" onClick={() => fileInputRef.current?.click()}>Browse Files</button>
                  <button className="btn-secondary" onClick={() => folderInputRef.current?.click()}>Select Folder</button>
                  {totalFiles > 0 && (
                    <button className="btn-secondary" onClick={clearAll} style={{ color: '#EB5757' }}>Clear All</button>
                  )}
                </div>
              </div>
            )}

            {/* Drive Panel */}
            {tab === 'drive' && (
              <div className="input-panel active">
                {driveApiReady === false && (
                  <div className="alert-warning">
                    <strong>⚙️ One-time setup required</strong>
                    <p style={{ marginTop: '0.4rem' }}>A Google Drive API key is required in HF Spaces Settings (Secrets). Please configure `GOOGLE_DRIVE_API_KEY`.</p>
                  </div>
                )}
                <div className="drive-input-wrap">
                  <input type="text" value={driveUrl} onChange={e => setDriveUrl(e.target.value)} placeholder="https://drive.google.com/drive/folders/…" />
                </div>
                <div className="drive-hint">
                  ⚠ The folder must be set to <strong>"Anyone with the link → Viewer"</strong>.<br/>
                  The app will download all .mzML / .mzXML files from the folder automatically.
                </div>
              </div>
            )}
            
            {error && <div className="alert-error" style={{marginTop: '1rem'}}>{error}</div>}
          </div>

          <div className="section-label">02 · CentWave Parameters</div>
          <div className="card">
            <div className="param-grid">
              <div className="param-item">
                <label>PPM Error</label>
                <input type="number" name="ppm" value={params.ppm} onChange={handleParamChange} />
                <div className="param-hint">Mass accuracy tolerance</div>
              </div>
              <div className="param-item">
                <label>S/N Threshold</label>
                <input type="number" name="sn" value={params.sn} onChange={handleParamChange} step="0.1" />
                <div className="param-hint">Signal-to-noise cutoff</div>
              </div>
              <div className="param-item">
                <label>Min Peakwidth (s)</label>
                <input type="number" name="min_pw" value={params.min_pw} onChange={handleParamChange} />
                <div className="param-hint">Shortest expected peak</div>
              </div>
              <div className="param-item">
                <label>Max Peakwidth (s)</label>
                <input type="number" name="max_pw" value={params.max_pw} onChange={handleParamChange} />
                <div className="param-hint">Increase for lipids</div>
              </div>
              <div className="param-item">
                <label>Prefilter k</label>
                <input type="number" name="pref_k" value={params.pref_k} onChange={handleParamChange} />
                <div className="param-hint">Min scans above I</div>
              </div>
              <div className="param-item">
                <label>Prefilter I</label>
                <input type="number" name="pref_i" value={params.pref_i} onChange={handleParamChange} />
                <div className="param-hint">Min intensity</div>
              </div>
            </div>
          </div>

          <div className="section-label">03 · Run</div>
          <div className="card">
            <button className="btn-run" onClick={startJob} disabled={isLoading || (tab==='local' && files.length===0) || (tab==='drive' && !driveUrl)}>
              {isLoading ? (
                <><span className="loader"></span> Processing... This may take a while depending on file size.</>
              ) : (
                <>⚡ Extract Peaks from All Files</>
              )}
            </button>
          </div>

          {/* Results section */}
          {(jobId || (stats && stats.errors?.length > 0)) && (
            <div className="results-section show">
              <div className="section-label">04 · Results</div>
              <div className="card">
                
                {stats && (
                  <div className="stats-row">
                    <div className="stat-box">
                      <div className="stat-val">{stats.successFiles}</div>
                      <div className="stat-label">Files Succeeded</div>
                    </div>
                    <div className="stat-box">
                      <div className="stat-val" style={{color: stats.errors?.length ? '#EB5757' : 'inherit'}}>{stats.errors?.length || 0}</div>
                      <div className="stat-label">Files Failed</div>
                    </div>
                  </div>
                )}
                
                {stats?.errors?.length > 0 && (
                  <div className="log-box" style={{marginBottom: '1rem'}}>
                    {stats.errors.map((e, i) => (
                      <span key={i} className="log-err">✗ {e.file}: {e.reason}<br/></span>
                    ))}
                  </div>
                )}

                {jobId && (
                  <a className="btn-download" href={`/api/peak-picker/download/${jobId}`}>
                    ⬇ Download Combined Results
                  </a>
                )}
              </div>
            </div>
          )}

        </div>

        {/* Sidebar */}
        <div className="sidebar">
          <div className="sidebar-card">
            <strong>References</strong>
            <p>[1] Tautenhahn R, Böttcher C, Neumann S. (2008). <em>Highly sensitive feature detection for high resolution LC/MS.</em> BMC Bioinformatics, 9:504.</p>
            <p>[2] Smith CA, et al. (2006). <em>XCMS: processing mass spectrometry data for metabolite profiling using nonlinear peak alignment, matching, and identification.</em> Anal. Chem., 78(3):779–787.</p>
          </div>
        </div>

      </div>
    </div>
  )
}
