import { useState, useEffect } from 'react'
import Timeline from '../components/Timeline.jsx'

const OPERATORS = ['BETWEEN', '=', '!=', 'IN', 'NOT IN', 'IS NULL', 'IS NOT NULL']

function buildFilterClause(filters) {
  if (!filters.length) return null
  const parts = filters.map(f => {
    const col = `"${f.col}"`
    const op = f.op
    if (op === 'IS NULL')     return `${col} IS NULL`
    if (op === 'IS NOT NULL') return `${col} IS NOT NULL`
    if (op === 'BETWEEN') {
      const [a, b] = f.values
      return `${col} BETWEEN '${a}' AND '${b}'`
    }
    if (op === 'IN' || op === 'NOT IN') {
      const vals = f.values.join("','")
      return `${col} ${op} ('${vals}')`
    }
    return `${col} ${op} '${f.values[0]}'`
  })
  return parts.join(' AND ')
}

function getDateRange(filters) {
  for (const f of filters) {
    if (f.op === 'BETWEEN' && f.values[0] && f.values[1]) {
      return { from: f.values[0], to: f.values[1] }
    }
    if (f.op === '=' && f.values[0]) {
      return { from: f.values[0], to: f.values[0] }
    }
  }
  return null
}

function parseDateRangeFromClause(clause) {
  if (!clause) return null
  const m = clause.match(/BETWEEN '(\d{4}-\d{2}-\d{2})' AND '(\d{4}-\d{2}-\d{2})'/)
  if (m) return { from: m[1], to: m[2] }
  const m2 = clause.match(/>= ?'(\d{4}-\d{2}-\d{2})'.+<= ?'(\d{4}-\d{2}-\d{2})'/)
  if (m2) return { from: m2[1], to: m2[2] }
  return null
}

function parseOffset(offsetStr) {
  if (!offsetStr || offsetStr === '0 days') return { yr: 0, mo: 0 }
  const yr = parseInt(offsetStr.match(/(\d+)\s+year/)?.[1] || 0)
  const mo = parseInt(offsetStr.match(/(\d+)\s+month/)?.[1] || 0)
  return { yr, mo }
}

function emptyFilter(cols) {
  return { col: cols[0]?.cname || '', op: 'BETWEEN', values: ['', ''] }
}

export default function Baseline() {
  const [sources,        setSources]        = useState([])
  const [sourceId,       setSourceId]       = useState('')
  const [versions,       setVersions]       = useState([])
  const [versionId,      setVersionId]      = useState('')
  const [filterCols,     setFilterCols]     = useState([])
  const [log,            setLog]            = useState([])

  // new version form
  const [showNewVersion, setShowNewVersion] = useState(false)
  const [newVerName,     setNewVerName]     = useState('')
  const [newVerDesc,     setNewVerDesc]     = useState('')
  const [creatingVer,    setCreatingVer]    = useState(false)

  // add segment form
  const [segType,        setSegType]        = useState('baseline')
  const [description,    setDescription]    = useState('')
  const [filters,        setFilters]        = useState([])
  const [offsetYr,       setOffsetYr]       = useState(0)
  const [offsetMo,       setOffsetMo]       = useState(0)
  const [segNote,        setSegNote]        = useState('')
  const [submitting,     setSubmitting]     = useState(false)

  const [expandedId,     setExpandedId]     = useState(null)
  const [msg,            setMsg]            = useState(null)

  useEffect(() => {
    fetch('/api/sources').then(r => r.json()).then(data => {
      setSources(data)
      if (data.length > 0) setSourceId(String(data[0].id))
    })
  }, [])

  useEffect(() => {
    if (!sourceId) return
    fetch(`/api/sources/${sourceId}/versions`).then(r => r.json()).then(data => {
      setVersions(data)
      if (data.length > 0) setVersionId(String(data[0].id))
      else setVersionId('')
    })
    fetch(`/api/sources/${sourceId}/cols`).then(r => r.json()).then(cols => {
      const fc = cols.filter(c => c.role === 'date' || c.role === 'filter')
      setFilterCols(fc)
      setFilters(fc.length > 0 ? [emptyFilter(fc)] : [])
    })
  }, [sourceId])

  useEffect(() => {
    if (!versionId) { setLog([]); return }
    loadLog()
  }, [versionId])

  function loadLog() {
    fetch(`/api/versions/${versionId}/log`).then(r => r.json()).then(data => {
      setLog(data.filter(e => e.operation === 'baseline' || e.operation === 'reference'))
    })
  }

  async function createVersion() {
    if (!newVerName.trim()) return
    setCreatingVer(true)
    try {
      const res = await fetch(`/api/sources/${sourceId}/versions`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name: newVerName.trim(), description: newVerDesc, created_by: 'admin' })
      })
      const data = await res.json()
      if (!res.ok) { flash(data.error, 'error'); return }
      const updated = await fetch(`/api/sources/${sourceId}/versions`).then(r => r.json())
      setVersions(updated)
      setVersionId(String(data.id))
      setShowNewVersion(false)
      setNewVerName('')
      setNewVerDesc('')
      flash(`Version "${data.name}" created`)
    } catch (err) {
      flash(err.message, 'error')
    } finally {
      setCreatingVer(false)
    }
  }

  function addFilter() {
    setFilters(f => [...f, emptyFilter(filterCols)])
  }

  function removeFilter(i) {
    setFilters(f => f.filter((_, idx) => idx !== i))
  }

  function updateFilter(i, field, value) {
    setFilters(f => f.map((row, idx) => {
      if (idx !== i) return row
      if (field === 'op') {
        const needsTwo  = value === 'BETWEEN'
        const needsOne  = ['=', '!='].includes(value)
        const needsMany = ['IN', 'NOT IN'].includes(value)
        const needsNone = ['IS NULL', 'IS NOT NULL'].includes(value)
        return { ...row, op: value, values: needsNone ? [] : needsTwo ? ['', ''] : needsMany ? [''] : [''] }
      }
      return { ...row, [field]: value }
    }))
  }

  function updateFilterValue(i, vi, value) {
    setFilters(f => f.map((row, idx) => {
      if (idx !== i) return row
      const vals = [...row.values]
      vals[vi] = value
      return { ...row, values: vals }
    }))
  }

  async function loadSegment() {
    const clause = buildFilterClause(filters)
    if (!clause) { flash('Add at least one filter', 'error'); return }
    const isRef = segType === 'reference'
    const offsetStr = isRef ? '0 days' : ([offsetYr > 0 ? `${offsetYr} year` : '', offsetMo > 0 ? `${offsetMo} month` : ''].filter(Boolean).join(' ') || '0 days')
    const endpoint = isRef ? 'reference' : 'baseline'
    const body = isRef
      ? { where_clause: clause, pf_user: 'admin', note: description || segNote }
      : { where_clause: clause, date_offset: offsetStr, pf_user: 'admin', note: description || segNote }
    setSubmitting(true)
    try {
      const res = await fetch(`/api/versions/${versionId}/${endpoint}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body)
      })
      const data = await res.json()
      if (!res.ok) { flash(data.error, 'error'); return }
      flash(`Loaded ${data.rows_affected ?? data.row_count ?? ''} rows`)
      loadLog()
      setDescription(''); setSegNote(''); setOffsetYr(0); setOffsetMo(0)
      setFilters(filterCols.length > 0 ? [emptyFilter(filterCols)] : [])
    } catch (err) {
      flash(err.message, 'error')
    } finally {
      setSubmitting(false)
    }
  }

  async function undoSegment(logid) {
    await fetch(`/api/log/${logid}`, { method: 'DELETE' })
    loadLog()
    flash('Segment undone')
  }

  async function clearBaseline() {
    if (!confirm('Delete all baseline rows for this version?')) return
    const res = await fetch(`/api/versions/${versionId}/baseline`, { method: 'DELETE' })
    const data = await res.json()
    if (!res.ok) { flash(data.error, 'error'); return }
    loadLog()
    flash(`Cleared ${data.rows_deleted} rows`)
  }

  async function closeVersion() {
    const res = await fetch(`/api/versions/${versionId}/close`, {
      method: 'POST', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ pf_user: 'admin' })
    })
    const data = await res.json()
    if (!res.ok) { flash(data.error, 'error'); return }
    const updated = await fetch(`/api/sources/${sourceId}/versions`).then(r => r.json())
    setVersions(updated)
    flash('Version closed')
  }

  async function reopenVersion() {
    const res = await fetch(`/api/versions/${versionId}/reopen`, { method: 'POST' })
    const data = await res.json()
    if (!res.ok) { flash(data.error, 'error'); return }
    const updated = await fetch(`/api/sources/${sourceId}/versions`).then(r => r.json())
    setVersions(updated)
    flash('Version reopened')
  }

  async function deleteVersion() {
    if (!confirm(`Delete version "${selectedVersion?.name}"? This drops the forecast table and cannot be undone.`)) return
    const res = await fetch(`/api/versions/${versionId}`, { method: 'DELETE' })
    const data = await res.json()
    if (!res.ok) { flash(data.error, 'error'); return }
    const updated = await fetch(`/api/sources/${sourceId}/versions`).then(r => r.json())
    setVersions(updated)
    setVersionId(updated.length > 0 ? String(updated[0].id) : '')
    flash('Version deleted')
  }

  function flash(text, type = 'ok') {
    setMsg({ text, type })
    setTimeout(() => setMsg(null), 3000)
  }

  const dateRange = getDateRange(filters)
  const selectedVersion = versions.find(v => String(v.id) === versionId)

  return (
    <div className="h-full overflow-y-auto bg-gray-50">
      <div className="p-4 flex flex-col gap-4 max-w-4xl">

        {/* Flash */}
        {msg && (
          <div className={`px-3 py-2 text-xs rounded font-medium ${msg.type === 'error' ? 'bg-red-50 text-red-700' : 'bg-green-50 text-green-700'}`}>
            {msg.text}
          </div>
        )}

        {/* Source + Version bar */}
        <div className="flex items-center gap-3 flex-wrap">
          <div className="flex items-center gap-2">
            <span className="text-xs text-gray-500">Source</span>
            <select value={sourceId} onChange={e => setSourceId(e.target.value)} className="border border-gray-200 rounded px-2 py-1 text-sm bg-white">
              {sources.map(s => <option key={s.id} value={s.id}>{s.tname}</option>)}
            </select>
          </div>
          <div className="flex items-center gap-2">
            <span className="text-xs text-gray-500">Version</span>
            <select value={versionId} onChange={e => setVersionId(e.target.value)} className="border border-gray-200 rounded px-2 py-1 text-sm bg-white" disabled={versions.length === 0}>
              {versions.length === 0
                ? <option value="">— no versions —</option>
                : versions.map(v => <option key={v.id} value={v.id}>{v.name}</option>)
              }
            </select>
            {versionId && (
              <span className={`text-xs font-medium ${selectedVersion?.status === 'open' ? 'text-green-600' : 'text-gray-400'}`}>
                {selectedVersion?.status}
              </span>
            )}
          </div>
          <button onClick={() => setShowNewVersion(v => !v)} className="text-xs text-blue-600 hover:text-blue-700 border border-blue-200 px-2 py-1 rounded">
            + New version
          </button>
          {versionId && (
            <div className="flex items-center gap-2 ml-2">
              {selectedVersion?.status === 'open'
                ? <button onClick={closeVersion} className="text-xs text-gray-500 hover:text-gray-700 border border-gray-200 px-2 py-1 rounded">Close</button>
                : <button onClick={reopenVersion} className="text-xs text-gray-500 hover:text-gray-700 border border-gray-200 px-2 py-1 rounded">Reopen</button>
              }
              <button onClick={deleteVersion} className="text-xs text-red-400 hover:text-red-600 border border-red-200 px-2 py-1 rounded">Delete</button>
            </div>
          )}
        </div>

        {/* New version inline form */}
        {showNewVersion && (
          <div className="bg-white border border-gray-200 rounded p-3 flex flex-col gap-3">
            <div className="flex items-end gap-3">
              <div className="flex flex-col gap-1">
                <label className="text-xs text-gray-500">Name</label>
                <input value={newVerName} onChange={e => setNewVerName(e.target.value)} placeholder="e.g. FY2026 Plan" className="border border-gray-200 rounded px-2 py-1 text-sm w-48" />
              </div>
              <div className="flex flex-col gap-1 flex-1">
                <label className="text-xs text-gray-500">Description</label>
                <input value={newVerDesc} onChange={e => setNewVerDesc(e.target.value)} placeholder="optional" className="border border-gray-200 rounded px-2 py-1 text-sm" />
              </div>
              <button onClick={createVersion} disabled={creatingVer || !newVerName.trim()} className="bg-blue-600 text-white text-xs px-3 py-1.5 rounded hover:bg-blue-700 disabled:opacity-50 shrink-0">
                {creatingVer ? 'Creating table…' : 'Create'}
              </button>
              <button onClick={() => setShowNewVersion(false)} className="text-gray-400 hover:text-gray-600 text-xs shrink-0">Cancel</button>
            </div>
            <div className="text-xs text-gray-400 border-t border-gray-100 pt-2">
              Creates a forecast table <span className="font-mono text-gray-500">pf.fc_{sources.find(s=>String(s.id)===sourceId)?.tname}_&lt;id&gt;</span> in the database from the current col meta. If col meta changes after creation the table and SQL will be out of sync — delete and recreate the version to realign.
            </div>
          </div>
        )}

        {versionId && <>

          {/* Segments loaded */}
          <div className="bg-white border border-gray-200 rounded">
            <div className="px-3 py-2 border-b border-gray-100 text-xs font-medium text-gray-500 uppercase tracking-wide flex items-center justify-between">
              <span>Segments loaded</span>
              <button onClick={clearBaseline} className="text-red-400 hover:text-red-600 text-xs normal-case font-normal">Clear all baseline</button>
            </div>
            <table className="w-full text-xs">
              <thead className="bg-gray-50">
                <tr className="text-left text-gray-400 border-b border-gray-100">
                  <th className="px-3 py-1.5 font-medium w-6"></th>
                  <th className="px-3 py-1.5 font-medium">#</th>
                  <th className="px-3 py-1.5 font-medium">note</th>
                  <th className="px-3 py-1.5 font-medium">by</th>
                  <th className="px-3 py-1.5 font-medium">when</th>
                  <th className="px-3 py-1.5 font-medium"></th>
                </tr>
              </thead>
              <tbody>
                {log.length === 0 && (
                  <tr><td colSpan={6} className="px-3 py-3 text-gray-300 italic">No segments loaded yet</td></tr>
                )}
                {log.map((entry, i) => {
                  const isOpen = expandedId === entry.id
                  const params = entry.params || {}
                  const dr = parseDateRangeFromClause(params.where_clause)
                  const off = parseOffset(params.date_offset)
                  return (
                    <>
                      <tr
                        key={entry.id}
                        onClick={() => setExpandedId(isOpen ? null : entry.id)}
                        className={`border-t border-gray-50 cursor-pointer hover:bg-gray-50 ${isOpen ? 'bg-blue-50' : ''}`}
                      >
                        <td className="px-3 py-2 text-gray-400 w-6">
                          <span className="text-gray-300 text-xs">{isOpen ? '▾' : '▸'}</span>
                        </td>
                        <td className="px-3 py-2 text-gray-400">{log.length - i}</td>
                        <td className="px-3 py-2">
                          <span className={`inline-block mr-2 px-1.5 py-0.5 rounded text-xs font-medium ${entry.operation === 'reference' ? 'bg-purple-50 text-purple-600' : 'bg-blue-50 text-blue-600'}`}>
                            {entry.operation}
                          </span>
                          {entry.note || <span className="text-gray-300">—</span>}
                        </td>
                        <td className="px-3 py-2 text-gray-500">{entry.pf_user}</td>
                        <td className="px-3 py-2 text-gray-400">{new Date(entry.stamp).toLocaleDateString()}</td>
                        <td className="px-3 py-2 text-right">
                          <button onClick={e => { e.stopPropagation(); undoSegment(entry.id) }} className="text-gray-400 hover:text-red-500 text-xs">Undo</button>
                        </td>
                      </tr>
                      {isOpen && (
                        <tr key={`${entry.id}-detail`} className="bg-blue-50 border-t border-blue-100">
                          <td colSpan={6} className="px-4 py-3">
                            <div className="flex flex-col gap-2">
                              <div className="flex items-start gap-2">
                                <span className="text-xs text-gray-400 w-24 shrink-0 pt-0.5">WHERE</span>
                                <code className="text-xs font-mono text-gray-700 bg-white border border-gray-200 rounded px-2 py-1 break-all">{params.where_clause || '—'}</code>
                              </div>
                              <div className="flex items-center gap-2">
                                <span className="text-xs text-gray-400 w-24 shrink-0">offset</span>
                                <span className="text-xs font-mono text-gray-600">{params.date_offset || '0 days'}</span>
                              </div>
                              {dr && (
                                <div className="mt-1">
                                  <Timeline dateFrom={dr.from} dateTo={dr.to} offsetYr={off.yr} offsetMo={off.mo} type={entry.operation === 'reference' ? 'reference' : 'baseline'} />
                                </div>
                              )}
                            </div>
                          </td>
                        </tr>
                      )}
                    </>
                  )
                })}
              </tbody>
            </table>
          </div>

          {/* Add Segment */}
          <div className="bg-white border border-gray-200 rounded">
            <div className="px-3 py-2 border-b border-gray-100 text-xs font-medium text-gray-500 uppercase tracking-wide">
              Add Segment
            </div>
            <div className="p-4 flex flex-col gap-4">

              {/* Type toggle */}
              <div className="flex items-center gap-3">
                <label className="text-xs text-gray-500 w-28 shrink-0">Type</label>
                <div className="flex rounded border border-gray-200 overflow-hidden text-xs">
                  {['baseline', 'reference'].map(t => (
                    <button
                      key={t}
                      onClick={() => { setSegType(t); if (t === 'reference') { setOffsetYr(0); setOffsetMo(0) } }}
                      className={`px-3 py-1 capitalize ${segType === t ? 'bg-blue-600 text-white' : 'bg-white text-gray-500 hover:bg-gray-50'}`}
                    >{t}</button>
                  ))}
                </div>
                {segType === 'reference' && (
                  <span className="text-xs text-gray-400">dates land verbatim — no offset applied</span>
                )}
              </div>

              {/* Description */}
              <div className="flex items-center gap-3">
                <label className="text-xs text-gray-500 w-28 shrink-0">Description</label>
                <input value={description} onChange={e => setDescription(e.target.value)} placeholder="e.g. FY25 actuals +1yr" className="border border-gray-200 rounded px-2 py-1.5 text-sm flex-1 max-w-sm" />
              </div>

              {/* Filters */}
              <div>
                <div className="flex items-center justify-between mb-2">
                  <label className="text-xs text-gray-500 w-28 shrink-0">Filters</label>
                  <button onClick={addFilter} className="text-blue-600 hover:text-blue-700 text-xs font-medium">+ Add filter</button>
                </div>
                <div className="flex flex-col gap-1.5 ml-28">
                  {filters.map((f, i) => {
                    const isDateCol = filterCols.find(c => c.cname === f.col)?.role === 'date'
                    return (
                    <div key={i} className="flex items-center gap-2 flex-wrap">
                      <select value={f.col} onChange={e => updateFilter(i, 'col', e.target.value)} className="border border-gray-200 rounded px-2 py-1 text-xs bg-white">
                        {filterCols.map(c => <option key={c.cname} value={c.cname}>{c.cname}</option>)}
                      </select>
                      <select value={f.op} onChange={e => updateFilter(i, 'op', e.target.value)} className="border border-gray-200 rounded px-2 py-1 text-xs bg-white">
                        {OPERATORS.map(op => <option key={op} value={op}>{op}</option>)}
                      </select>
                      {f.op === 'BETWEEN' && <>
                        <input type={isDateCol ? 'date' : 'text'} value={f.values[0]} onChange={e => updateFilterValue(i, 0, e.target.value)} placeholder="from" className="border border-gray-200 rounded px-2 py-1 text-xs w-36 font-mono bg-white" />
                        <span className="text-gray-400 text-xs">and</span>
                        <input type={isDateCol ? 'date' : 'text'} value={f.values[1]} onChange={e => updateFilterValue(i, 1, e.target.value)} placeholder="to" className="border border-gray-200 rounded px-2 py-1 text-xs w-36 font-mono bg-white" />
                      </>}
                      {(f.op === '=' || f.op === '!=') && (
                        <input type={isDateCol ? 'date' : 'text'} value={f.values[0]} onChange={e => updateFilterValue(i, 0, e.target.value)} placeholder="value" className="border border-gray-200 rounded px-2 py-1 text-xs w-36 font-mono bg-white" />
                      )}
                      {(f.op === 'IN' || f.op === 'NOT IN') && (
                        <input value={f.values[0]} onChange={e => updateFilterValue(i, 0, e.target.value)} placeholder="val1, val2, …" className="border border-gray-200 rounded px-2 py-1 text-xs w-48 font-mono bg-white" />
                      )}
                      <button onClick={() => removeFilter(i)} className="text-gray-300 hover:text-red-400 text-xs">✕</button>
                    </div>
                    )
                  })}
                  {filters.length === 0 && (
                    <span className="text-xs text-gray-300 italic">No filters — at least one is required</span>
                  )}
                </div>
              </div>

              {/* Date offset — baseline only */}
              {segType === 'baseline' && (
                <div className="flex items-center gap-3">
                  <label className="text-xs text-gray-500 w-28 shrink-0">Date offset</label>
                  <div className="flex items-center gap-2">
                    <input type="number" value={offsetYr} min={0} onChange={e => setOffsetYr(parseInt(e.target.value) || 0)} className="border border-gray-200 rounded px-2 py-1 text-sm w-16 text-center bg-white" />
                    <span className="text-xs text-gray-500">yr</span>
                    <input type="number" value={offsetMo} min={0} max={11} onChange={e => setOffsetMo(parseInt(e.target.value) || 0)} className="border border-gray-200 rounded px-2 py-1 text-sm w-16 text-center bg-white" />
                    <span className="text-xs text-gray-500">mo</span>
                  </div>
                </div>
              )}

              {/* Timeline */}
              {dateRange && (
                <div className="ml-28">
                  <div className="bg-gray-50 border border-gray-200 rounded p-3">
                    <Timeline
                      dateFrom={dateRange.from}
                      dateTo={dateRange.to}
                      offsetYr={segType === 'baseline' ? offsetYr : 0}
                      offsetMo={segType === 'baseline' ? offsetMo : 0}
                      type={segType}
                    />
                  </div>
                </div>
              )}

              {/* Note + submit */}
              <div className="flex items-end gap-3">
                <div className="flex flex-col gap-1 flex-1 max-w-xs">
                  <label className="text-xs text-gray-500">Note</label>
                  <input value={segNote} onChange={e => setSegNote(e.target.value)} placeholder="optional" className="border border-gray-200 rounded px-2 py-1.5 text-sm" />
                </div>
                <button onClick={loadSegment} disabled={submitting || filters.length === 0} className="bg-blue-600 text-white text-xs px-5 py-2 rounded hover:bg-blue-700 disabled:opacity-50 shrink-0">
                  {submitting ? 'Loading…' : `Load ${segType === 'reference' ? 'Reference' : 'Segment'}`}
                </button>
              </div>

            </div>
          </div>

        </>}

      </div>
    </div>
  )
}
