import { useEffect, useMemo, useState } from 'react'
import { ApiHttpError } from '../../api/http'
import {
  createConfigurationEntry,
  deleteConfigurationEntry,
  fetchConfigurations,
  updateConfigurationEntry,
} from '../../api/session'
import type { ConfigurationRow } from '../../api/types'

export function ConfigurationViewPage() {
  const [rows, setRows] = useState<ConfigurationRow[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [flash, setFlash] = useState<string | null>(null)
  const [sortKey, setSortKey] = useState<'id' | 'config_key' | 'config_value'>('config_key')
  const [sortDir, setSortDir] = useState<'asc' | 'desc'>('asc')
  const [page, setPage] = useState(1)
  const pageSize = 25

  const [showAdd, setShowAdd] = useState(false)
  const [newKey, setNewKey] = useState('')
  const [newVal, setNewVal] = useState('')

  const [editOpen, setEditOpen] = useState(false)
  const [editRow, setEditRow] = useState<ConfigurationRow | null>(null)
  const [editKey, setEditKey] = useState('')
  const [editVal, setEditVal] = useState('')
  const [busy, setBusy] = useState(false)

  async function reload() {
    setLoading(true)
    setError(null)
    try {
      const data = await fetchConfigurations()
      setRows(data.configs ?? [])
    } catch (e: unknown) {
      setError(e instanceof ApiHttpError ? e.message : 'Failed to load configuration.')
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    void reload()
  }, [])

  async function onAdd(e: React.FormEvent) {
    e.preventDefault()
    if (!newKey.trim() || !newVal.trim()) return
    setBusy(true)
    setFlash(null)
    try {
      await createConfigurationEntry({ config_key: newKey.trim(), config_value: newVal.trim() })
      setFlash('Saved.')
      setNewKey('')
      setNewVal('')
      setShowAdd(false)
      await reload()
    } catch (err: unknown) {
      setFlash(err instanceof ApiHttpError ? err.message : 'Save failed.')
    } finally {
      setBusy(false)
    }
  }

  function openEdit(row: ConfigurationRow) {
    setEditRow(row)
    setEditKey(row.config_key)
    setEditVal(row.config_value)
    setEditOpen(true)
  }

  async function onEditSave(e: React.FormEvent) {
    e.preventDefault()
    if (!editRow) return
    setBusy(true)
    setFlash(null)
    try {
      await updateConfigurationEntry(editRow.id, {
        config_key: editKey.trim(),
        config_value: editVal.trim(),
      })
      setFlash('Updated.')
      setEditOpen(false)
      setEditRow(null)
      await reload()
    } catch (err: unknown) {
      setFlash(err instanceof ApiHttpError ? err.message : 'Update failed.')
    } finally {
      setBusy(false)
    }
  }

  async function onDelete(id: number | string) {
    if (!window.confirm('Are you sure you want to delete this config?')) return
    setBusy(true)
    setFlash(null)
    try {
      await deleteConfigurationEntry(id)
      setFlash('Deleted.')
      await reload()
    } catch (err: unknown) {
      setFlash(err instanceof ApiHttpError ? err.message : 'Delete failed.')
    } finally {
      setBusy(false)
    }
  }

  const sortedRows = useMemo(() => {
    const items = [...rows]
    const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' })

    const valueFor = (row: ConfigurationRow): string => {
      switch (sortKey) {
        case 'id':
          return String(row.id ?? '')
        case 'config_value':
          return String(row.config_value ?? '')
        case 'config_key':
        default:
          return String(row.config_key ?? '')
      }
    }

    items.sort((a, b) => {
      const result = collator.compare(valueFor(a), valueFor(b))
      return sortDir === 'asc' ? result : -result
    })

    return items
  }, [rows, sortDir, sortKey])

  const totalPages = Math.max(1, Math.ceil(sortedRows.length / pageSize))
  const currentPage = Math.min(page, totalPages)
  const pagedRows = useMemo(() => {
    const start = (currentPage - 1) * pageSize
    return sortedRows.slice(start, start + pageSize)
  }, [currentPage, sortedRows])

  function toggleSort(nextKey: 'id' | 'config_key' | 'config_value') {
    if (sortKey === nextKey) {
      setSortDir((current) => (current === 'asc' ? 'desc' : 'asc'))
      setPage(1)
      return
    }
    setSortKey(nextKey)
    setSortDir('asc')
    setPage(1)
  }

  function sortIndicator(key: 'id' | 'config_key' | 'config_value') {
    if (sortKey !== key) return ''
    return sortDir === 'asc' ? ' ▲' : ' ▼'
  }

  function renderSortableHeader(
    key: 'id' | 'config_key' | 'config_value',
    label: string,
  ) {
    return (
      <button
        type="button"
        onClick={() => toggleSort(key)}
        style={{
          background: 'transparent',
          border: 0,
          color: 'inherit',
          font: 'inherit',
          fontWeight: 600,
          padding: 0,
          textAlign: 'left',
        }}
      >
        {label}
        {sortIndicator(key)}
      </button>
    )
  }

  return (
    <div className="container-fluid py-3">
      <div className="text-center mb-4">
        <h2 className="mt-4 mb-3">Configuration Management</h2>
      </div>

      {flash ? (
        <div className={`alert ${flash.includes('fail') ? 'alert-danger' : 'alert-success'}`}>{flash}</div>
      ) : null}

      {loading ? (
        <p className="text-muted text-center">Loading configurations…</p>
      ) : error ? (
        <div className="alert alert-danger">{error}</div>
      ) : null}

      {showAdd ? (
        <form onSubmit={onAdd} className="mb-4 border rounded p-3 bg-light">
          <div className="row">
            <div className="col-md-4 mb-3">
              <label className="form-label" htmlFor="new_config_key">
                Config Key
              </label>
              <input
                id="new_config_key"
                className="form-control"
                value={newKey}
                onChange={(ev) => setNewKey(ev.target.value)}
                required
              />
            </div>
            <div className="col-md-4 mb-3">
              <label className="form-label" htmlFor="new_config_value">
                Config Value
              </label>
              <input
                id="new_config_value"
                className="form-control"
                value={newVal}
                onChange={(ev) => setNewVal(ev.target.value)}
                required
              />
            </div>
          </div>
          <div className="d-flex gap-2">
            <button type="submit" className="btn btn-primary" disabled={busy}>
              Save
            </button>
            <button type="button" className="btn btn-secondary" onClick={() => setShowAdd(false)}>
              Cancel
            </button>
          </div>
        </form>
      ) : null}

      <div className="d-flex justify-content-end mb-3">
        <button type="button" className="btn btn-success" onClick={() => setShowAdd((v) => !v)}>
          {showAdd ? 'Hide form' : 'Add New Config'}
        </button>
      </div>

      <div className="table-responsive">
        <table className="table table-striped align-middle">
          <thead>
            <tr>
              <th>{renderSortableHeader('id', 'ID')}</th>
              <th>{renderSortableHeader('config_key', 'Config Key')}</th>
              <th>{renderSortableHeader('config_value', 'Config Value')}</th>
              <th>Actions</th>
            </tr>
          </thead>
          <tbody>
            {!loading && rows.length === 0 ? (
              <tr>
                <td colSpan={4} className="text-center text-muted">
                  No configurations found.
                </td>
              </tr>
            ) : (
              pagedRows.map((row) => (
                <tr key={String(row.id)}>
                  <td>{String(row.id)}</td>
                  <td>{row.config_key}</td>
                  <td>{row.config_value}</td>
                  <td className="d-flex gap-1 flex-wrap">
                    <button
                      type="button"
                      className="btn btn-sm btn-warning"
                      onClick={() => openEdit(row)}
                      disabled={busy}
                    >
                      Edit
                    </button>
                    <button
                      type="button"
                      className="btn btn-sm btn-danger"
                      onClick={() => void onDelete(row.id)}
                      disabled={busy}
                    >
                      Delete
                    </button>
                  </td>
                </tr>
              ))
            )}
          </tbody>
        </table>
      </div>

      {!loading && rows.length > 0 ? (
        <div className="d-flex flex-wrap justify-content-between align-items-center gap-2 mt-3">
          <div className="text-muted small">
            Showing {(currentPage - 1) * pageSize + 1}-{Math.min(currentPage * pageSize, sortedRows.length)} of{' '}
            {sortedRows.length} configurations
          </div>
          <div className="btn-group" role="group" aria-label="Pagination">
            <button
              type="button"
              className="btn btn-outline-secondary btn-sm"
              disabled={currentPage <= 1}
              onClick={() => setPage(1)}
            >
              First
            </button>
            <button
              type="button"
              className="btn btn-outline-secondary btn-sm"
              disabled={currentPage <= 1}
              onClick={() => setPage((p) => Math.max(1, p - 1))}
            >
              Previous
            </button>
            <button type="button" className="btn btn-outline-secondary btn-sm" disabled>
              Page {currentPage} of {totalPages}
            </button>
            <button
              type="button"
              className="btn btn-outline-secondary btn-sm"
              disabled={currentPage >= totalPages}
              onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
            >
              Next
            </button>
            <button
              type="button"
              className="btn btn-outline-secondary btn-sm"
              disabled={currentPage >= totalPages}
              onClick={() => setPage(totalPages)}
            >
              Last
            </button>
          </div>
        </div>
      ) : null}

      {editOpen ? (
        <div className="modal fade show d-block" tabIndex={-1} style={{ background: 'rgba(0,0,0,0.4)' }}>
          <div className="modal-dialog">
            <form className="modal-content" onSubmit={onEditSave}>
              <div className="modal-header">
                <h5 className="modal-title">Edit Configuration</h5>
                <button
                  type="button"
                  className="btn-close"
                  aria-label="Close"
                  onClick={() => setEditOpen(false)}
                />
              </div>
              <div className="modal-body">
                <div className="mb-3">
                  <label className="form-label" htmlFor="modal_config_key">
                    Config Key
                  </label>
                  <input
                    id="modal_config_key"
                    className="form-control"
                    value={editKey}
                    onChange={(ev) => setEditKey(ev.target.value)}
                    required
                  />
                </div>
                <div className="mb-3">
                  <label className="form-label" htmlFor="modal_config_value">
                    Config Value
                  </label>
                  <input
                    id="modal_config_value"
                    className="form-control"
                    value={editVal}
                    onChange={(ev) => setEditVal(ev.target.value)}
                    required
                  />
                </div>
              </div>
              <div className="modal-footer">
                <button type="button" className="btn btn-secondary" onClick={() => setEditOpen(false)}>
                  Cancel
                </button>
                <button type="submit" className="btn btn-primary" disabled={busy}>
                  Save changes
                </button>
              </div>
            </form>
          </div>
        </div>
      ) : null}
    </div>
  )
}
