import { useState, useEffect, useRef } from 'react'
import { useSearchParams } from 'react-router-dom'
import { api } from '../api'

const FIELD_TYPES = ['text', 'numeric', 'date']

function SampleTable({ rows }) {
  if (!rows || rows.length === 0) return null
  const cols = Object.keys(rows[0])
  return (
    <div className="overflow-auto border border-gray-100 rounded bg-gray-50 max-h-36">
      <table className="text-xs w-full">
        <thead>
          <tr className="text-left text-gray-400 border-b border-gray-100 bg-gray-50 sticky top-0">
            {cols.map(c => <th key={c} className="px-2 py-1 font-medium whitespace-nowrap">{c}</th>)}
          </tr>
        </thead>
        <tbody>
          {rows.map((row, i) => (
            <tr key={i} className="border-t border-gray-100">
              {cols.map(c => (
                <td key={c} className="px-2 py-1 whitespace-nowrap text-gray-600 max-w-32 truncate font-mono">
                  {row[c] == null ? <span className="text-gray-300">—</span> : String(row[c])}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  )
}

export default function Sources({ source, sources, setSources, setSource }) {
  const [constraintFields, setConstraintFields] = useState('')
  const [globalPicklist, setGlobalPicklist] = useState(true)
  const [schemaFields, setSchemaFields] = useState([])
  const [stats, setStats] = useState(null)
  const [sampleRows, setSampleRows] = useState([])
  const [saving, setSaving] = useState(false)
  const [reprocessing, setReprocessing] = useState(false)
  const [generating, setGenerating] = useState(false)
  const [result, setResult] = useState('')
  const [error, setError] = useState('')
  const [viewName, setViewName] = useState('')
  const [availableFields, setAvailableFields] = useState([])
  const [fieldSort, setFieldSort] = useState({ col: 'key', dir: 'asc' })
  const [creating, setCreating] = useState(false)
  const [form, setForm] = useState({ name: '', constraint_fields: '', fields: [], schema: [], importSample: true })
  const [createError, setCreateError] = useState('')
  const [createLoading, setCreateLoading] = useState(false)
  const [csvFileName, setCsvFileName] = useState('')
  const fileRef = useRef()

  const [searchParams, setSearchParams] = useSearchParams()
  const sourceObj = sources.find(s => s.name === source)

  useEffect(() => {
    if (searchParams.get('new') === '1') {
      setCreating(true)
      setSearchParams({})
    }
  }, [searchParams])

  useEffect(() => {
    if (!sourceObj) return
    setConstraintFields(sourceObj.constraint_fields?.join(', ') || '')
    setGlobalPicklist(sourceObj.global_picklist !== false)
    setSchemaFields((sourceObj.config?.fields || []).map((f, i) => ({ seq: i + 1, ...f })))
    setViewName(sourceObj.config?.fields?.length ? `dfv.${sourceObj.name}` : '')
    setResult('')
    setError('')
    setStats(null)
    setAvailableFields([])
    setSampleRows([])
    api.getStats(sourceObj.name).then(setStats).catch(() => {})
    api.getFields(sourceObj.name).then(setAvailableFields).catch(() => {})
    api.getRecords(sourceObj.name, 50).then(rows => setSampleRows(rows.map(r => r.data).filter(Boolean))).catch(() => {})
  }, [source, sourceObj?.name])

  async function handleSave(e) {
    e.preventDefault()
    setSaving(true)
    setError('')
    try {
      const constraint_fields = constraintFields.split(',').map(s => s.trim()).filter(Boolean)
      const fields = [...schemaFields.filter(f => f.name)].sort((a, b) => (a.seq ?? 0) - (b.seq ?? 0))
      const config = { ...(sourceObj.config || {}), fields }
      await api.updateSource(sourceObj.name, { constraint_fields, config, global_picklist: globalPicklist })
      if (fields.length > 0) {
        const res = await api.generateView(sourceObj.name)
        if (res.success) setViewName(res.view)
      }
      const updated = await api.getSources()
      setSources(updated)
      setResult('Saved.')
    } catch (err) {
      setError(err.message)
    } finally {
      setSaving(false)
    }
  }

  async function handleGenerateView() {
    setGenerating(true)
    setResult('')
    setError('')
    try {
      const constraint_fields = constraintFields.split(',').map(s => s.trim()).filter(Boolean)
      const fields = [...schemaFields.filter(f => f.name)].sort((a, b) => (a.seq ?? 0) - (b.seq ?? 0))
      const config = { ...(sourceObj.config || {}), fields }
      await api.updateSource(sourceObj.name, { constraint_fields, config, global_picklist: globalPicklist })
      const res = await api.generateView(sourceObj.name)
      if (res.success) {
        setViewName(res.view)
        setResult(`View created: ${res.view}`)
      } else {
        setError(res.error)
      }
    } catch (err) {
      setError(err.message)
    } finally {
      setGenerating(false)
    }
  }

  async function handleReprocess() {
    if (!confirm(`Reprocess all records for "${sourceObj.name}"? This will clear and reapply all transformations.`)) return
    setReprocessing(true)
    setResult('')
    setError('')
    try {
      const res = await api.reprocess(sourceObj.name)
      setResult(`Reprocessed ${res.transformed} records.`)
      api.getStats(sourceObj.name).then(setStats).catch(() => {})
    } catch (err) {
      setError(err.message)
    } finally {
      setReprocessing(false)
    }
  }

  async function handleDelete() {
    if (!confirm(`Delete source "${sourceObj.name}" and all its data?`)) return
    try {
      await api.deleteSource(sourceObj.name)
      const updated = await api.getSources()
      setSources(updated)
      if (updated.length > 0) setSource(updated[0].name)
      else setSource('')
    } catch (err) {
      alert(err.message)
    }
  }

  async function handleSuggest(e) {
    const file = e.target.files[0]
    if (!file) return
    setCsvFileName(file.name)
    try {
      const suggestion = await api.suggestSource(file)
      setForm(f => ({
        ...f,
        fields: suggestion.fields,
        constraint_fields: '',
        schema: suggestion.fields.map(f => ({ name: f.name, type: f.type, seq: suggestion.fields.indexOf(f) + 1 })),
        sampleRows: suggestion.sampleRows || []
      }))
    } catch (err) {
      setCreateError(err.message)
    }
  }

  async function handleCreate(e) {
    e.preventDefault()
    setCreateError('')
    const constraintArr = form.constraint_fields.split(',').map(s => s.trim()).filter(Boolean)
    if (!form.name || constraintArr.length === 0) {
      setCreateError('Name and at least one constraint field required')
      return
    }
    setCreateLoading(true)
    try {
      const config = form.schema.length > 0 ? { fields: form.schema } : {}
      await api.createSource({ name: form.name, constraint_fields: constraintArr, config, global_picklist: form.global_picklist !== false })
      if (form.schema.length > 0) {
        await api.generateView(form.name)
      }
      if (form.importSample && fileRef.current?.files[0]) {
        await api.importCSV(form.name, fileRef.current.files[0])
      }
      const updated = await api.getSources()
      setSources(updated)
      setSource(form.name)
      setForm({ name: '', constraint_fields: '', fields: [], schema: [], importSample: true })
      setCreating(false)
    } catch (err) {
      setCreateError(err.message)
    } finally {
      setCreateLoading(false)
    }
  }

  return (
    <div className="p-6 max-w-5xl">
      <div className="flex items-center justify-between mb-6">
        <h1 className="text-xl font-semibold text-gray-800">
          {sourceObj ? sourceObj.name : 'Sources'}
        </h1>
        <button
          onClick={() => { setCreating(true); setCreateError('') }}
          className="text-sm bg-blue-600 text-white px-3 py-1.5 rounded hover:bg-blue-700"
        >
          New source
        </button>
      </div>

      {/* No source selected */}
      {!sourceObj && !creating && (
        <p className="text-sm text-gray-400">No sources yet. Create one to get started.</p>
      )}

      {/* Source detail */}
      {sourceObj && !creating && (
        <div className="space-y-4">
          {/* Stats */}
          {stats && (
            <div className="flex gap-4 text-xs">
              <span className="text-gray-500"><span className="font-medium text-gray-800">{stats.total_records}</span> total</span>
              <span className="text-gray-500"><span className="font-medium text-gray-800">{stats.transformed_records}</span> transformed</span>
              <span className="text-gray-500"><span className="font-medium text-gray-800">{stats.pending_records}</span> pending</span>
            </div>
          )}

          {/* Unified field table */}
          {availableFields.length > 0 && (
            <div className="pt-2 border-t border-gray-100 space-y-2">
              <table className="w-full text-xs">
                <thead>
                  <tr className="text-left text-gray-400 border-b border-gray-100">
                    {[
                      { col: 'key', label: 'Key' },
                      { col: 'origin', label: 'Origin' },
                      { col: 'type', label: 'Type' },
                      { col: 'constraint', label: 'Constraint', center: true },
                      { col: 'inview', label: 'In view', center: true },
                      { col: 'seq', label: 'Seq', center: true },
                    ].map(({ col, label, center }) => (
                      <th
                        key={col}
                        onClick={() => setFieldSort(s => ({ col, dir: s.col === col && s.dir === 'asc' ? 'desc' : 'asc' }))}
                        className={`pb-1 font-medium cursor-pointer select-none hover:text-gray-600 ${center ? 'text-center' : ''}`}
                      >
                        {label}
                        <span className="ml-1 text-gray-300">
                          {fieldSort.col === col ? (fieldSort.dir === 'asc' ? '▲' : '▼') : '⇅'}
                        </span>
                      </th>
                    ))}
                  </tr>
                </thead>
                <tbody>
                  {[...availableFields].sort((a, b) => {
                    const constraintList = constraintFields.split(',').map(s => s.trim())
                    const aSchema = schemaFields.find(sf => sf.name === a.key)
                    const bSchema = schemaFields.find(sf => sf.name === b.key)
                    let av, bv
                    if (fieldSort.col === 'key') { av = a.key; bv = b.key }
                    else if (fieldSort.col === 'origin') { av = a.origins.join(','); bv = b.origins.join(',') }
                    else if (fieldSort.col === 'type') { av = aSchema?.type || ''; bv = bSchema?.type || '' }
                    else if (fieldSort.col === 'constraint') { av = constraintList.includes(a.key) ? 0 : 1; bv = constraintList.includes(b.key) ? 0 : 1 }
                    else if (fieldSort.col === 'inview') { av = aSchema ? 0 : 1; bv = bSchema ? 0 : 1 }
                    else if (fieldSort.col === 'seq') { av = aSchema?.seq ?? 999; bv = bSchema?.seq ?? 999 }
                    if (av < bv) return fieldSort.dir === 'asc' ? -1 : 1
                    if (av > bv) return fieldSort.dir === 'asc' ? 1 : -1
                    return 0
                  }).map(f => {
                    const isRaw = f.origins.includes('raw')
                    const constraintChecked = constraintFields.split(',').map(s => s.trim()).includes(f.key)
                    const schemaEntry = schemaFields.find(sf => sf.name === f.key)
                    const inView = !!schemaEntry
                    return (
                      <tr key={f.key} className="border-t border-gray-50">
                        <td className="py-1 font-mono text-gray-700">{f.key}</td>
                        <td className="py-1 text-gray-400">{f.origins.join(', ')}</td>
                        <td className="py-1">
                          {inView && (
                            <div className="flex gap-1 items-center">
                              <select
                                className="border border-gray-200 rounded px-1 py-0.5 text-xs focus:outline-none focus:border-blue-400"
                                value={schemaEntry.type}
                                onChange={e => setSchemaFields(sf =>
                                  sf.map(s => s.name === f.key ? { ...s, type: e.target.value } : s)
                                )}
                              >
                                {FIELD_TYPES.map(t => <option key={t} value={t}>{t}</option>)}
                              </select>
                              <input
                                className="border border-gray-200 rounded px-1 py-0.5 text-xs font-mono w-32 focus:outline-none focus:border-blue-400"
                                value={schemaEntry.expression || ''}
                                placeholder="{field} * {sign}"
                                onChange={e => setSchemaFields(sf =>
                                  sf.map(s => s.name === f.key ? { ...s, expression: e.target.value || undefined } : s)
                                )}
                              />
                            </div>
                          )}
                        </td>
                        <td className="py-1 text-center">
                          {isRaw && (
                            <input
                              type="checkbox"
                              checked={constraintChecked}
                              onChange={e => {
                                const current = constraintFields.split(',').map(s => s.trim()).filter(Boolean)
                                const next = e.target.checked
                                  ? [...current, f.key]
                                  : current.filter(k => k !== f.key)
                                setConstraintFields(next.join(', '))
                              }}
                            />
                          )}
                        </td>
                        <td className="py-1 text-center">
                          <input
                            type="checkbox"
                            checked={inView}
                            onChange={e => {
                              if (e.target.checked) {
                                const nextSeq = schemaFields.length > 0
                                  ? Math.max(...schemaFields.map(s => s.seq ?? 0)) + 1
                                  : 1
                                setSchemaFields(sf => [...sf, { name: f.key, type: 'text', seq: nextSeq }])
                              } else {
                                setSchemaFields(sf => sf.filter(s => s.name !== f.key))
                              }
                            }}
                          />
                        </td>
                        <td className="py-1 text-center">
                          {inView && (
                            <input
                              type="number"
                              className="w-12 border border-gray-200 rounded px-1 py-0.5 text-xs text-center focus:outline-none focus:border-blue-400"
                              value={schemaEntry.seq ?? ''}
                              onChange={e => setSchemaFields(sf =>
                                sf.map(s => s.name === f.key ? { ...s, seq: parseInt(e.target.value) || 0 } : s)
                              )}
                            />
                          )}
                        </td>
                      </tr>
                    )
                  })}
                </tbody>
              </table>

              <div className="flex items-center gap-3 pt-1 flex-wrap">
                <label className="flex items-center gap-1.5 text-xs text-gray-500 cursor-pointer">
                  <input type="checkbox" checked={globalPicklist} onChange={e => setGlobalPicklist(e.target.checked)} />
                  Global picklist
                </label>
                <form onSubmit={handleSave}>
                  <button type="submit" disabled={saving}
                    className="text-sm bg-blue-600 text-white px-3 py-1.5 rounded hover:bg-blue-700 disabled:opacity-50">
                    {saving ? 'Saving…' : 'Save'}
                  </button>
                </form>
                {schemaFields.length > 0 && (
                  <>
                    <button
                      onClick={handleGenerateView}
                      disabled={generating}
                      className="text-xs bg-green-600 text-white px-2 py-1.5 rounded hover:bg-green-700 disabled:opacity-50"
                    >
                      {generating ? 'Generating…' : 'Generate view'}
                    </button>
                    {viewName && (
                      <code className="text-xs bg-gray-100 px-2 py-1 rounded text-gray-600">{viewName}</code>
                    )}
                  </>
                )}
              </div>
              <SampleTable rows={sampleRows} />
            </div>
          )}

          {/* Save button when no fields loaded yet */}
          {availableFields.length === 0 && (
            <div className="flex items-center gap-3">
              <label className="flex items-center gap-1.5 text-xs text-gray-500 cursor-pointer">
                <input type="checkbox" checked={globalPicklist} onChange={e => setGlobalPicklist(e.target.checked)} />
                Global picklist
              </label>
              <form onSubmit={handleSave}>
                <button type="submit" disabled={saving}
                  className="text-sm bg-blue-600 text-white px-3 py-1.5 rounded hover:bg-blue-700 disabled:opacity-50">
                  {saving ? 'Saving…' : 'Save'}
                </button>
              </form>
            </div>
          )}

          {/* Reprocess */}
          <div className="flex items-center gap-3 pt-2 border-t border-gray-100">
            <button
              onClick={handleReprocess}
              disabled={reprocessing}
              className="text-sm bg-orange-500 text-white px-3 py-1.5 rounded hover:bg-orange-600 disabled:opacity-50"
            >
              {reprocessing ? 'Reprocessing…' : 'Reprocess all records'}
            </button>
            <span className="text-xs text-gray-400">Clears and reruns all transformation rules</span>
          </div>

          {result && <p className="text-xs text-green-600">{result}</p>}
          {error && <p className="text-xs text-red-500">{error}</p>}

          <div className="pt-2 border-t border-gray-100">
            <button onClick={handleDelete} className="text-xs text-red-400 hover:text-red-600">
              Delete source
            </button>
          </div>
        </div>
      )}

      {/* Create form */}
      {creating && (
        <div className="bg-white border border-gray-200 rounded p-4">
          <h2 className="text-sm font-semibold text-gray-700 mb-3">New source</h2>

          <div className="mb-4">
            <input type="file" accept=".csv" ref={fileRef} onChange={handleSuggest} className="hidden" />
            <button
              type="button"
              onClick={() => fileRef.current?.click()}
              className="text-sm border border-gray-300 rounded px-3 py-1.5 text-gray-600 hover:bg-gray-50 hover:border-gray-400"
            >
              {csvFileName || 'Choose CSV…'}
            </button>
          </div>

          <form onSubmit={handleCreate} className="space-y-3">
            <div>
              <label className="text-xs text-gray-500 block mb-1">Source name</label>
              <input
                className="w-full border border-gray-200 rounded px-3 py-1.5 text-sm focus:outline-none focus:border-blue-400"
                value={form.name}
                onChange={e => setForm(f => ({ ...f, name: e.target.value }))}
                placeholder="e.g. chase, dcard"
              />
            </div>

            {form.fields.length > 0 && (
              <div className="pt-2 border-t border-gray-100 space-y-2">
                <table className="w-full text-xs">
                  <thead>
                    <tr className="text-left text-gray-400 border-b border-gray-100">
                      <th className="pb-1 font-medium">Key</th>
                      <th className="pb-1 font-medium">Type</th>
                      <th className="pb-1 font-medium text-center">Constraint</th>
                      <th className="pb-1 font-medium text-center">In view</th>
                      <th className="pb-1 font-medium text-center">Seq</th>
                    </tr>
                  </thead>
                  <tbody>
                    {form.fields.map(f => {
                      const schemaEntry = form.schema.find(s => s.name === f.name)
                      const inView = !!schemaEntry
                      const currentType = schemaEntry?.type || f.type
                      return (
                        <tr key={f.name} className="border-t border-gray-50">
                          <td className="py-1 font-mono text-gray-700">{f.name}</td>
                          <td className="py-1">
                            {inView && (
                              <select
                                className="border border-gray-200 rounded px-1 py-0.5 text-xs focus:outline-none focus:border-blue-400"
                                value={currentType}
                                onChange={e => setForm(ff => ({
                                  ...ff,
                                  schema: ff.schema.map(s => s.name === f.name ? { ...s, type: e.target.value } : s)
                                }))}
                              >
                                {FIELD_TYPES.map(t => <option key={t} value={t}>{t}</option>)}
                              </select>
                            )}
                          </td>
                          <td className="py-1 text-center">
                            <input
                              type="checkbox"
                              checked={form.constraint_fields.split(',').map(s => s.trim()).includes(f.name)}
                              onChange={e => {
                                const current = form.constraint_fields.split(',').map(s => s.trim()).filter(Boolean)
                                const next = e.target.checked
                                  ? [...current, f.name]
                                  : current.filter(n => n !== f.name)
                                setForm(ff => ({ ...ff, constraint_fields: next.join(', ') }))
                              }}
                            />
                          </td>
                          <td className="py-1 text-center">
                            <input
                              type="checkbox"
                              checked={inView}
                              onChange={e => {
                                if (e.target.checked) {
                                  const nextSeq = form.schema.length > 0
                                    ? Math.max(...form.schema.map(s => s.seq ?? 0)) + 1
                                    : 1
                                  setForm(ff => ({ ...ff, schema: [...ff.schema, { name: f.name, type: f.type, seq: nextSeq }] }))
                                } else {
                                  setForm(ff => ({ ...ff, schema: ff.schema.filter(s => s.name !== f.name) }))
                                }
                              }}
                            />
                          </td>
                          <td className="py-1 text-center">
                            {inView && (
                              <input
                                type="number"
                                className="w-12 border border-gray-200 rounded px-1 py-0.5 text-xs text-center focus:outline-none focus:border-blue-400"
                                value={schemaEntry.seq ?? ''}
                                onChange={e => setForm(ff => ({
                                  ...ff,
                                  schema: ff.schema.map(s => s.name === f.name ? { ...s, seq: parseInt(e.target.value) || 0 } : s)
                                }))}
                              />
                            )}
                          </td>
                        </tr>
                      )
                    })}
                  </tbody>
                </table>
                <SampleTable rows={form.sampleRows || []} />
              </div>
            )}

            {form.fields.length === 0 && (
              <div>
                <label className="text-xs text-gray-500 block mb-1">Constraint fields (comma-separated)</label>
                <input
                  className="w-full border border-gray-200 rounded px-3 py-1.5 text-sm focus:outline-none focus:border-blue-400"
                  value={form.constraint_fields}
                  onChange={e => setForm(f => ({ ...f, constraint_fields: e.target.value }))}
                  placeholder="e.g. date, amount, description"
                />
              </div>
            )}

            <div className="flex gap-4">
              <label className="flex items-center gap-1.5 text-xs text-gray-500 cursor-pointer">
                <input
                  type="checkbox"
                  checked={form.global_picklist !== false}
                  onChange={e => setForm(f => ({ ...f, global_picklist: e.target.checked }))}
                />
                Global picklist
              </label>
              {form.fields.length > 0 && (
                <label className="flex items-center gap-1.5 text-xs text-gray-500 cursor-pointer">
                  <input
                    type="checkbox"
                    checked={form.importSample !== false}
                    onChange={e => setForm(f => ({ ...f, importSample: e.target.checked }))}
                  />
                  Import sample data
                </label>
              )}
            </div>

            {createError && <p className="text-xs text-red-500">{createError}</p>}

            <div className="flex gap-2">
              <button type="submit" disabled={createLoading}
                className="text-sm bg-blue-600 text-white px-3 py-1.5 rounded hover:bg-blue-700 disabled:opacity-50">
                {createLoading ? 'Creating…' : 'Create'}
              </button>
              <button type="button"
                onClick={() => { setCreating(false); setCreateError(''); setForm({ name: '', constraint_fields: '', fields: [], schema: [] }) }}
                className="text-sm text-gray-500 px-3 py-1.5 rounded hover:bg-gray-100">
                Cancel
              </button>
            </div>
          </form>
        </div>
      )}
    </div>
  )
}
