// vibe_erp List View Designer page.
//
// Configuration editor for metadata list view definitions.
// Lets admins define columns (visibility, label, format, sortable,
// order), filters, default sort, and page size for any entity's
// list view. A live preview DataTable renders placeholder rows
// using the selected columns.
//
// Edit mode: when the URL carries a :slug param the page fetches
// the existing definition and populates all fields for editing.
// Create mode: all fields start blank / with sensible defaults.

import { useCallback, useEffect, useMemo, useState, type FormEvent } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { metadata } from '@/api/client'
import { PageHeader } from '@/components/PageHeader'
import { ErrorBox } from '@/components/ErrorBox'
import { DataTable, type Column } from '@/components/DataTable'
import { useT } from '@/i18n/LocaleContext'

// ─── Designer state types ──────────────────────────────────────────

interface DesignerColumn {
  field: string
  label: string
  width?: string
  sortable: boolean
  format?: string
  visible: boolean
}

interface DesignerFilter {
  field: string
  operator: string
  label: string
}

interface DesignerState {
  slug: string
  entityName: string
  title: string
  columns: DesignerColumn[]
  defaultSort?: { field: string; direction: 'asc' | 'desc' }
  filters: DesignerFilter[]
  pageSize: number
  version: number
}

const FORMAT_OPTIONS = ['plain', 'date', 'money', 'status-badge', 'link'] as const
const OPERATOR_OPTIONS = ['eq', 'contains', 'gt', 'lt', 'in'] as const

function emptyState(): DesignerState {
  return {
    slug: '',
    entityName: '',
    title: '',
    columns: [],
    defaultSort: undefined,
    filters: [],
    pageSize: 25,
    version: 0,
  }
}

// ─── Component ─────────────────────────────────────────────────────

export function ListViewDesignerPage() {
  const navigate = useNavigate()
  const t = useT()
  const { slug: routeSlug } = useParams<{ slug: string }>()
  const isEdit = Boolean(routeSlug)

  const [state, setState] = useState<DesignerState>(emptyState)
  const [loading, setLoading] = useState(isEdit)
  const [saving, setSaving] = useState(false)
  const [error, setError] = useState<unknown>(null)

  // ── Load existing definition in edit mode ──────────────────────
  useEffect(() => {
    if (!routeSlug) return
    setLoading(true)
    metadata
      .getListView(routeSlug)
      .then((def) => {
        setState({
          slug: def.slug,
          entityName: def.entityName,
          title: def.title,
          columns: def.columns.map((c) => ({
            field: c.field,
            label: c.label,
            width: c.width,
            sortable: c.sortable,
            format: c.format ?? 'plain',
            visible: true,
          })),
          defaultSort: def.defaultSort,
          filters: def.filters ?? [],
          pageSize: def.pageSize,
          version: def.version,
        })
      })
      .catch(setError)
      .finally(() => setLoading(false))
  }, [routeSlug])

  // ── Field updaters ─────────────────────────────────────────────

  const set = useCallback(
    <K extends keyof DesignerState>(key: K, val: DesignerState[K]) =>
      setState((s) => ({ ...s, [key]: val })),
    [],
  )

  // ── Column helpers ─────────────────────────────────────────────

  const updateColumn = useCallback(
    (idx: number, patch: Partial<DesignerColumn>) =>
      setState((s) => {
        const cols = [...s.columns]
        cols[idx] = { ...cols[idx], ...patch }
        return { ...s, columns: cols }
      }),
    [],
  )

  const moveColumn = useCallback(
    (idx: number, dir: -1 | 1) =>
      setState((s) => {
        const target = idx + dir
        if (target < 0 || target >= s.columns.length) return s
        const cols = [...s.columns]
        ;[cols[idx], cols[target]] = [cols[target], cols[idx]]
        return { ...s, columns: cols }
      }),
    [],
  )

  const removeColumn = useCallback(
    (idx: number) =>
      setState((s) => ({
        ...s,
        columns: s.columns.filter((_, i) => i !== idx),
      })),
    [],
  )

  const addColumn = useCallback(
    () =>
      setState((s) => ({
        ...s,
        columns: [
          ...s.columns,
          { field: '', label: '', sortable: false, format: 'plain', visible: true },
        ],
      })),
    [],
  )

  // ── Filter helpers ─────────────────────────────────────────────

  const updateFilter = useCallback(
    (idx: number, patch: Partial<DesignerFilter>) =>
      setState((s) => {
        const filters = [...s.filters]
        filters[idx] = { ...filters[idx], ...patch }
        return { ...s, filters }
      }),
    [],
  )

  const removeFilter = useCallback(
    (idx: number) =>
      setState((s) => ({
        ...s,
        filters: s.filters.filter((_, i) => i !== idx),
      })),
    [],
  )

  const addFilter = useCallback(
    () =>
      setState((s) => ({
        ...s,
        filters: [...s.filters, { field: '', operator: 'eq', label: '' }],
      })),
    [],
  )

  // ── Save ───────────────────────────────────────────────────────

  const onSave = async (e: FormEvent) => {
    e.preventDefault()
    setError(null)
    setSaving(true)
    try {
      const slug = state.slug.trim()
      if (!slug) throw new Error('Slug is required')
      if (!state.entityName.trim()) throw new Error('Entity name is required')

      const visibleColumns = state.columns
        .filter((c) => c.visible)
        .map((c) => ({
          field: c.field,
          label: c.label,
          width: c.width || undefined,
          sortable: c.sortable,
          format: c.format === 'plain' ? undefined : (c.format as 'date' | 'money' | 'status-badge' | 'link'),
        }))

      await metadata.saveListView(slug, {
        slug,
        entityName: state.entityName,
        title: state.title,
        columns: visibleColumns,
        defaultSort: state.defaultSort,
        filters: state.filters.filter((f) => f.field.trim()),
        pageSize: state.pageSize,
        version: state.version + 1,
      })
      navigate('/admin/metadata')
    } catch (err: unknown) {
      setError(err)
    } finally {
      setSaving(false)
    }
  }

  // ── Preview columns for DataTable ──────────────────────────────

  const previewColumns: Column<Record<string, string>>[] = useMemo(
    () =>
      state.columns
        .filter((c) => c.visible && c.field.trim())
        .map((c) => ({
          header: c.label || c.field,
          key: c.field,
        })),
    [state.columns],
  )

  const previewRows = useMemo(() => {
    if (previewColumns.length === 0) return []
    const rows: Record<string, string>[] = []
    for (let i = 1; i <= 3; i++) {
      const row: Record<string, string> = {}
      for (const col of previewColumns) {
        row[col.key] = `${col.key}-${i}`
      }
      rows.push(row)
    }
    return rows
  }, [previewColumns])

  // ── Render ─────────────────────────────────────────────────────

  if (loading) {
    return (
      <div className="p-6 text-sm text-slate-500">{t('label.loading')}</div>
    )
  }

  const inputCls =
    'mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm shadow-sm focus:border-brand-500 focus:ring-brand-500'
  const smallInputCls =
    'rounded-md border border-slate-300 px-2 py-1.5 text-sm shadow-sm focus:border-brand-500 focus:ring-brand-500'
  const smallSelectCls =
    'rounded-md border border-slate-300 px-2 py-1.5 text-sm shadow-sm focus:border-brand-500 focus:ring-brand-500'

  return (
    <div>
      <PageHeader
        title={isEdit ? t('page.listViewDesigner.editTitle') : t('page.listViewDesigner.newTitle')}
        subtitle={t('page.listViewDesigner.subtitle')}
        actions={
          <button
            className="btn-secondary"
            onClick={() => navigate('/admin/metadata')}
          >
            {t('action.cancel')}
          </button>
        }
      />

      <form onSubmit={onSave} className="space-y-6 max-w-5xl">
        {error != null ? <ErrorBox error={error} /> : null}

        {/* ── Top bar: title, entity, slug ───────────────────── */}
        <div className="card p-6 space-y-4">
          <h2 className="text-lg font-semibold text-slate-800">{t('label.general')}</h2>
          <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
            <div>
              <label className="block text-sm font-medium text-slate-700">
                {t('label.title')}
              </label>
              <input
                type="text"
                required
                value={state.title}
                onChange={(e) => set('title', e.target.value)}
                placeholder="e.g. Sales Orders"
                className={inputCls}
              />
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700">
                {t('label.entityName')}
              </label>
              <input
                type="text"
                required
                value={state.entityName}
                onChange={(e) => set('entityName', e.target.value)}
                placeholder="e.g. SalesOrder"
                className={inputCls}
              />
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700">
                {t('label.slug')}
              </label>
              <input
                type="text"
                required
                value={state.slug}
                onChange={(e) => set('slug', e.target.value)}
                placeholder="e.g. sales-orders-default"
                disabled={isEdit}
                className={`${inputCls}${isEdit ? ' bg-slate-50 text-slate-500' : ''}`}
              />
            </div>
          </div>
        </div>

        {/* ── Columns section ────────────────────────────────── */}
        <div className="card p-6 space-y-4">
          <div className="flex items-center justify-between">
            <h2 className="text-lg font-semibold text-slate-800">{t('label.columns')}</h2>
            <button
              type="button"
              className="btn-secondary text-xs"
              onClick={addColumn}
            >
              {t('action.addColumn')}
            </button>
          </div>

          {state.columns.length === 0 ? (
            <p className="text-sm text-slate-400">
              {t('label.noColumnsHint')}
            </p>
          ) : (
            <div className="overflow-x-auto">
              <table className="table-base text-sm">
                <thead className="bg-slate-50">
                  <tr>
                    <th className="w-10">{t('label.show')}</th>
                    <th>{t('label.field')}</th>
                    <th>{t('label.label')}</th>
                    <th className="w-28">{t('label.format')}</th>
                    <th className="w-16">{t('label.sortable')}</th>
                    <th className="w-24">{t('label.orderMeta')}</th>
                    <th className="w-10"></th>
                  </tr>
                </thead>
                <tbody className="divide-y divide-slate-100">
                  {state.columns.map((col, idx) => (
                    <tr key={idx} className="hover:bg-slate-50">
                      <td className="text-center">
                        <input
                          type="checkbox"
                          checked={col.visible}
                          onChange={(e) =>
                            updateColumn(idx, { visible: e.target.checked })
                          }
                          className="h-4 w-4 rounded border-slate-300 text-brand-600 focus:ring-brand-500"
                        />
                      </td>
                      <td>
                        <input
                          type="text"
                          value={col.field}
                          onChange={(e) =>
                            updateColumn(idx, { field: e.target.value })
                          }
                          placeholder="field.name"
                          className={smallInputCls + ' w-full'}
                        />
                      </td>
                      <td>
                        <input
                          type="text"
                          value={col.label}
                          onChange={(e) =>
                            updateColumn(idx, { label: e.target.value })
                          }
                          placeholder="Column Label"
                          className={smallInputCls + ' w-full'}
                        />
                      </td>
                      <td>
                        <select
                          value={col.format ?? 'plain'}
                          onChange={(e) =>
                            updateColumn(idx, { format: e.target.value })
                          }
                          className={smallSelectCls + ' w-full'}
                        >
                          {FORMAT_OPTIONS.map((f) => (
                            <option key={f} value={f}>
                              {f}
                            </option>
                          ))}
                        </select>
                      </td>
                      <td className="text-center">
                        <input
                          type="checkbox"
                          checked={col.sortable}
                          onChange={(e) =>
                            updateColumn(idx, { sortable: e.target.checked })
                          }
                          className="h-4 w-4 rounded border-slate-300 text-brand-600 focus:ring-brand-500"
                        />
                      </td>
                      <td>
                        <div className="flex items-center justify-center gap-1">
                          <button
                            type="button"
                            className="rounded p-1 text-slate-400 hover:bg-slate-100 hover:text-slate-600 disabled:opacity-30"
                            disabled={idx === 0}
                            onClick={() => moveColumn(idx, -1)}
                            title={t('label.moveUp')}
                          >
                            &#9650;
                          </button>
                          <button
                            type="button"
                            className="rounded p-1 text-slate-400 hover:bg-slate-100 hover:text-slate-600 disabled:opacity-30"
                            disabled={idx === state.columns.length - 1}
                            onClick={() => moveColumn(idx, 1)}
                            title={t('label.moveDown')}
                          >
                            &#9660;
                          </button>
                        </div>
                      </td>
                      <td>
                        <button
                          type="button"
                          className="text-slate-400 hover:text-rose-500"
                          onClick={() => removeColumn(idx)}
                          title={t('label.removeColumn')}
                        >
                          &times;
                        </button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>

        {/* ── Filters section ────────────────────────────────── */}
        <div className="card p-6 space-y-4">
          <div className="flex items-center justify-between">
            <h2 className="text-lg font-semibold text-slate-800">{t('label.filters')}</h2>
            <button
              type="button"
              className="btn-secondary text-xs"
              onClick={addFilter}
            >
              {t('action.addFilter')}
            </button>
          </div>

          {state.filters.length === 0 ? (
            <p className="text-sm text-slate-400">
              {t('label.noFiltersHint')}
            </p>
          ) : (
            <div className="space-y-2">
              {state.filters.map((filter, idx) => (
                <div key={idx} className="flex items-center gap-2">
                  <input
                    type="text"
                    value={filter.field}
                    onChange={(e) =>
                      updateFilter(idx, { field: e.target.value })
                    }
                    placeholder={t('label.fieldName')}
                    className={smallInputCls + ' flex-1'}
                  />
                  <select
                    value={filter.operator}
                    onChange={(e) =>
                      updateFilter(idx, { operator: e.target.value })
                    }
                    className={smallSelectCls + ' w-28'}
                  >
                    {OPERATOR_OPTIONS.map((op) => (
                      <option key={op} value={op}>
                        {op}
                      </option>
                    ))}
                  </select>
                  <input
                    type="text"
                    value={filter.label}
                    onChange={(e) =>
                      updateFilter(idx, { label: e.target.value })
                    }
                    placeholder={t('label.displayLabel')}
                    className={smallInputCls + ' flex-1'}
                  />
                  <button
                    type="button"
                    className="text-slate-400 hover:text-rose-500"
                    onClick={() => removeFilter(idx)}
                    title={t('label.removeFilter')}
                  >
                    &times;
                  </button>
                </div>
              ))}
            </div>
          )}
        </div>

        {/* ── Sorting & page size section ────────────────────── */}
        <div className="card p-6 space-y-4">
          <h2 className="text-lg font-semibold text-slate-800">
            {t('label.sortingPagination')}
          </h2>
          <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
            <div>
              <label className="block text-sm font-medium text-slate-700">
                {t('label.defaultSortField')}
              </label>
              <select
                value={state.defaultSort?.field ?? ''}
                onChange={(e) => {
                  const field = e.target.value
                  if (!field) {
                    set('defaultSort', undefined)
                  } else {
                    set('defaultSort', {
                      field,
                      direction: state.defaultSort?.direction ?? 'asc',
                    })
                  }
                }}
                className={inputCls}
              >
                <option value="">{t('label.none')}</option>
                {state.columns
                  .filter((c) => c.field.trim())
                  .map((c) => (
                    <option key={c.field} value={c.field}>
                      {c.label || c.field}
                    </option>
                  ))}
              </select>
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700">
                {t('label.direction')}
              </label>
              <select
                value={state.defaultSort?.direction ?? 'asc'}
                onChange={(e) => {
                  if (!state.defaultSort) return
                  set('defaultSort', {
                    ...state.defaultSort,
                    direction: e.target.value as 'asc' | 'desc',
                  })
                }}
                disabled={!state.defaultSort}
                className={`${inputCls}${!state.defaultSort ? ' bg-slate-50 text-slate-500' : ''}`}
              >
                <option value="asc">{t('label.ascending')}</option>
                <option value="desc">{t('label.descending')}</option>
              </select>
            </div>
            <div>
              <label className="block text-sm font-medium text-slate-700">
                {t('label.pageSize')}
              </label>
              <input
                type="number"
                min={1}
                max={500}
                value={state.pageSize}
                onChange={(e) =>
                  set('pageSize', Math.max(1, parseInt(e.target.value, 10) || 25))
                }
                className={inputCls}
              />
            </div>
          </div>
        </div>

        {/* ── Preview section ────────────────────────────────── */}
        <div className="card p-6 space-y-4">
          <h2 className="text-lg font-semibold text-slate-800">{t('label.preview')}</h2>
          {previewColumns.length === 0 ? (
            <p className="text-sm text-slate-400">
              {t('label.addColumnsHint')}
            </p>
          ) : (
            <DataTable
              rows={previewRows}
              columns={previewColumns}
              rowKey={(r) => String(r[previewColumns[0]?.key] ?? '')}
            />
          )}
        </div>

        {/* ── Actions ────────────────────────────────────────── */}
        <div className="flex items-center gap-3">
          <button type="submit" className="btn-primary" disabled={saving}>
            {saving ? t('action.saving') : t('action.saveListView')}
          </button>
          <button
            type="button"
            className="btn-secondary"
            onClick={() => navigate('/admin/metadata')}
          >
            {t('action.cancel')}
          </button>
        </div>
      </form>
    </div>
  )
}
