/**
 * View Designer — Criteria grid (SSMS Query Designer'in orta bolumu).
 *
 * Sutunlar: Column · Alias · Table · Output · Group By · Sort Type · Sort Order
 * · Filter · Or... Filtre hucreleri serbest yuklemdir ("> 100", "LIKE '%a%'");
 * yaninda kucuk bir yardimci ile de doldurulabilir.
 */
import { useState } from 'react'
import { FaCode, FaGripVertical, FaMagic, FaPlus, FaTrash } from 'react-icons/fa'
import type { DatabaseColumnDto } from '@/proxy/sql-query-manager/models'
import {
  GROUP_MODES,
  GROUP_MODE_LABEL,
  isAggregateMode,
  orColumnCount,
  quoteLiteral,
  type CriteriaRow,
  type GroupMode,
  type ViewSource,
} from './viewModel'

interface CriteriaGridProps {
  rows: CriteriaRow[]
  sources: ViewSource[]
  columnsOf: (sourceId: string) => DatabaseColumnDto[]
  grouped: boolean
  onUpdateRow: (id: string, patch: Partial<CriteriaRow>) => void
  onUpdateFilter: (id: string, index: number, value: string) => void
  onRemoveRow: (id: string) => void
  onMoveRow: (id: string, delta: number) => void
  onAddRow: () => void
  onAddExpression: () => void
  labels: {
    column: string
    alias: string
    table: string
    output: string
    groupBy: string
    sortType: string
    sortOrder: string
    filter: string
    or: string
    addRow: string
    addExpression: string
    expressionPlaceholder: string
    empty: string
    builder: string
    builderValue: string
    builderLiteral: string
    builderExpression: string
    apply: string
  }
}

const OPERATORS = [
  '=',
  '<>',
  '>',
  '>=',
  '<',
  '<=',
  'LIKE',
  'NOT LIKE',
  'IN',
  'NOT IN',
  'IS NULL',
  'IS NOT NULL',
  'BETWEEN',
]

export function CriteriaGrid({
  rows,
  sources,
  columnsOf,
  grouped,
  onUpdateRow,
  onUpdateFilter,
  onRemoveRow,
  onMoveRow,
  onAddRow,
  onAddExpression,
  labels,
}: CriteriaGridProps) {
  const [builder, setBuilder] = useState<{ rowId: string; index: number } | null>(null)

  const orCount = orColumnCount(rows)

  const cellCls =
    'w-full rounded border border-transparent bg-transparent px-1 py-0.5 text-xs hover:border-gray-300 focus:border-blue-500 focus:bg-white dark:text-gray-100 dark:hover:border-gray-600 dark:focus:bg-gray-700'

  return (
    <div className="flex h-full flex-col overflow-hidden rounded-lg border border-gray-200 dark:border-gray-700">
      <div className="flex items-center gap-2 border-b border-gray-200 bg-gray-50 px-2 py-1 dark:border-gray-700 dark:bg-gray-800">
        <button
          type="button"
          className="flex items-center gap-1 rounded px-1.5 py-0.5 text-[11px] text-blue-600 hover:bg-blue-50 dark:hover:bg-blue-900/30"
          onClick={onAddRow}
          disabled={sources.length === 0}
        >
          <FaPlus className="text-[9px]" /> {labels.addRow}
        </button>
        <button
          type="button"
          className="flex items-center gap-1 rounded px-1.5 py-0.5 text-[11px] text-indigo-600 hover:bg-indigo-50 dark:hover:bg-indigo-900/30"
          onClick={onAddExpression}
        >
          <FaCode className="text-[9px]" /> {labels.addExpression}
        </button>
        <span className="text-[10px] text-gray-400">{rows.length}</span>
      </div>

      <div className="flex-1 overflow-auto">
        <table className="w-full border-collapse text-xs">
          <thead className="sticky top-0 z-10 bg-gray-100 text-[10px] font-semibold uppercase tracking-wide text-gray-500 dark:bg-gray-800 dark:text-gray-300">
            <tr>
              <th className="w-6 border border-gray-200 px-1 py-1 dark:border-gray-700" />
              <th className="min-w-[150px] border border-gray-200 px-1 py-1 text-left dark:border-gray-700">
                {labels.column}
              </th>
              <th className="min-w-[110px] border border-gray-200 px-1 py-1 text-left dark:border-gray-700">
                {labels.alias}
              </th>
              <th className="min-w-[90px] border border-gray-200 px-1 py-1 text-left dark:border-gray-700">
                {labels.table}
              </th>
              <th className="w-14 border border-gray-200 px-1 py-1 dark:border-gray-700">
                {labels.output}
              </th>
              {grouped && (
                <th className="min-w-[110px] border border-gray-200 px-1 py-1 text-left dark:border-gray-700">
                  {labels.groupBy}
                </th>
              )}
              <th className="w-[86px] border border-gray-200 px-1 py-1 text-left dark:border-gray-700">
                {labels.sortType}
              </th>
              <th className="w-[70px] border border-gray-200 px-1 py-1 text-left dark:border-gray-700">
                {labels.sortOrder}
              </th>
              {Array.from({ length: orCount }).map((_, i) => (
                <th
                  key={i}
                  className="min-w-[130px] border border-gray-200 px-1 py-1 text-left dark:border-gray-700"
                >
                  {i === 0 ? labels.filter : labels.or}
                </th>
              ))}
              <th className="w-8 border border-gray-200 px-1 py-1 dark:border-gray-700" />
            </tr>
          </thead>
          <tbody>
            {rows.length === 0 && (
              <tr>
                <td
                  className="border border-gray-200 px-2 py-6 text-center text-xs text-gray-400 dark:border-gray-700"
                  colSpan={(grouped ? 9 : 8) + orCount}
                >
                  {labels.empty}
                </td>
              </tr>
            )}
            {rows.map((row) => {
              const isAgg = grouped && isAggregateMode(row.groupMode)
              const isExpression = row.expression !== undefined
              return (
                <tr
                  key={row.id}
                  className={
                    row.output ? 'bg-white dark:bg-gray-900' : 'bg-gray-50/70 dark:bg-gray-800/40'
                  }
                >
                  <td className="border border-gray-200 px-0.5 text-center dark:border-gray-700">
                    <div className="flex flex-col items-center leading-none">
                      <button
                        type="button"
                        className="text-[8px] text-gray-300 hover:text-blue-500"
                        onClick={() => onMoveRow(row.id, -1)}
                      >
                        ▲
                      </button>
                      <FaGripVertical className="text-[8px] text-gray-300" />
                      <button
                        type="button"
                        className="text-[8px] text-gray-300 hover:text-blue-500"
                        onClick={() => onMoveRow(row.id, 1)}
                      >
                        ▼
                      </button>
                    </div>
                  </td>

                  <td className="border border-gray-200 px-0.5 dark:border-gray-700">
                    {isExpression ? (
                      <input
                        className={`${cellCls} font-mono text-[11px] text-indigo-700 dark:text-indigo-300`}
                        placeholder={labels.expressionPlaceholder}
                        value={row.expression ?? ''}
                        title={row.expression}
                        onChange={(e) => onUpdateRow(row.id, { expression: e.target.value })}
                      />
                    ) : (
                      <select
                        className={cellCls}
                        value={row.columnName}
                        onChange={(e) => onUpdateRow(row.id, { columnName: e.target.value })}
                      >
                        <option value="">—</option>
                        {columnsOf(row.sourceId).map((c) => (
                          <option key={c.columnName} value={c.columnName}>
                            {c.columnName}
                          </option>
                        ))}
                      </select>
                    )}
                  </td>

                  <td className="border border-gray-200 px-0.5 dark:border-gray-700">
                    <input
                      className={cellCls}
                      placeholder={row.columnName}
                      value={row.alias}
                      onChange={(e) => onUpdateRow(row.id, { alias: e.target.value })}
                    />
                  </td>

                  <td className="border border-gray-200 px-0.5 dark:border-gray-700">
                    {isExpression ? (
                      <span className="px-1 text-[10px] italic text-gray-400">SQL</span>
                    ) : (
                      <select
                        className={cellCls}
                        value={row.sourceId}
                        onChange={(e) =>
                          onUpdateRow(row.id, { sourceId: e.target.value, columnName: '' })
                        }
                      >
                        {sources.map((s) => (
                          <option key={s.id} value={s.id}>
                            {s.alias || s.objectName}
                          </option>
                        ))}
                      </select>
                    )}
                  </td>

                  <td className="border border-gray-200 text-center dark:border-gray-700">
                    <input
                      type="checkbox"
                      className="h-3.5 w-3.5"
                      checked={row.output}
                      disabled={row.groupMode === 'Where'}
                      onChange={(e) => onUpdateRow(row.id, { output: e.target.checked })}
                    />
                  </td>

                  {grouped && (
                    <td className="border border-gray-200 px-0.5 dark:border-gray-700">
                      <select
                        className={cellCls}
                        value={row.groupMode}
                        disabled={isExpression}
                        onChange={(e) => {
                          const mode = e.target.value as GroupMode
                          onUpdateRow(row.id, {
                            groupMode: mode,
                            ...(mode === 'Where' ? { output: false } : {}),
                          })
                        }}
                      >
                        {GROUP_MODES.map((m) => (
                          <option key={m} value={m}>
                            {GROUP_MODE_LABEL[m]}
                          </option>
                        ))}
                      </select>
                    </td>
                  )}

                  <td className="border border-gray-200 px-0.5 dark:border-gray-700">
                    <select
                      className={cellCls}
                      value={row.sortType}
                      onChange={(e) => {
                        const sortType = e.target.value as '' | 'ASC' | 'DESC'
                        onUpdateRow(row.id, {
                          sortType,
                          sortOrder: sortType
                            ? row.sortOrder || rows.filter((r) => r.sortType).length + 1
                            : 0,
                        })
                      }}
                    >
                      <option value="">—</option>
                      <option value="ASC">Ascending</option>
                      <option value="DESC">Descending</option>
                    </select>
                  </td>

                  <td className="border border-gray-200 px-0.5 dark:border-gray-700">
                    <input
                      type="number"
                      min={0}
                      className={cellCls}
                      value={row.sortOrder || ''}
                      disabled={!row.sortType}
                      onChange={(e) =>
                        onUpdateRow(row.id, { sortOrder: Number(e.target.value) || 0 })
                      }
                    />
                  </td>

                  {Array.from({ length: orCount }).map((_, i) => (
                    <td
                      key={i}
                      className="relative border border-gray-200 px-0.5 dark:border-gray-700"
                    >
                      <div className="flex items-center gap-0.5">
                        <input
                          className={cellCls}
                          placeholder={i === 0 ? "> 100 · = 'A' · IS NULL" : ''}
                          value={row.filters[i] ?? ''}
                          onChange={(e) => onUpdateFilter(row.id, i, e.target.value)}
                        />
                        <button
                          type="button"
                          className="shrink-0 text-[9px] text-gray-300 hover:text-blue-500"
                          title={labels.builder}
                          onClick={() =>
                            setBuilder(
                              builder?.rowId === row.id && builder.index === i
                                ? null
                                : { rowId: row.id, index: i },
                            )
                          }
                        >
                          <FaMagic />
                        </button>
                      </div>
                      {builder?.rowId === row.id && builder.index === i && (
                        <FilterBuilder
                          labels={labels}
                          onApply={(text) => {
                            onUpdateFilter(row.id, i, text)
                            setBuilder(null)
                          }}
                          onClose={() => setBuilder(null)}
                        />
                      )}
                      {isAgg && (row.filters[i] ?? '').trim() && (
                        <span className="pointer-events-none absolute -top-1 right-6 rounded bg-indigo-100 px-1 text-[8px] font-semibold text-indigo-700 dark:bg-indigo-900/50 dark:text-indigo-300">
                          HAVING
                        </span>
                      )}
                    </td>
                  ))}

                  <td className="border border-gray-200 text-center dark:border-gray-700">
                    <button
                      type="button"
                      className="text-[10px] text-gray-400 hover:text-red-500"
                      onClick={() => onRemoveRow(row.id)}
                    >
                      <FaTrash />
                    </button>
                  </td>
                </tr>
              )
            })}
          </tbody>
        </table>
      </div>
    </div>
  )
}

// ─── Filtre yardimcisi ────────────────────────────────────────────────────────

function FilterBuilder({
  labels,
  onApply,
  onClose,
}: {
  labels: CriteriaGridProps['labels']
  onApply: (text: string) => void
  onClose: () => void
}) {
  const [operator, setOperator] = useState('=')
  const [value, setValue] = useState('')
  const [value2, setValue2] = useState('')
  const [mode, setMode] = useState<'literal' | 'expression'>('literal')

  const needsValue = operator !== 'IS NULL' && operator !== 'IS NOT NULL'

  const build = () => {
    if (!needsValue) return operator
    const render = (v: string) => (mode === 'literal' ? quoteLiteral(v.trim()) : v.trim())
    if (operator === 'BETWEEN') return `BETWEEN ${render(value)} AND ${render(value2)}`
    if (operator === 'IN' || operator === 'NOT IN') {
      if (mode === 'expression') return `${operator} (${value.trim()})`
      const items = value
        .split(',')
        .map((v) => v.trim())
        .filter(Boolean)
        .map(quoteLiteral)
      return `${operator} (${items.join(', ')})`
    }
    return `${operator} ${render(value)}`
  }

  return (
    <div
      className="absolute left-0 top-full z-50 mt-1 w-[230px] rounded-lg border border-gray-200 bg-white p-2 shadow-xl dark:border-gray-700 dark:bg-gray-800"
      onClick={(e) => e.stopPropagation()}
    >
      <select
        className="mb-1 w-full rounded border px-1 py-1 text-xs dark:border-gray-600 dark:bg-gray-700 dark:text-white"
        value={operator}
        onChange={(e) => setOperator(e.target.value)}
      >
        {OPERATORS.map((op) => (
          <option key={op} value={op}>
            {op}
          </option>
        ))}
      </select>
      {needsValue && (
        <>
          <input
            className="mb-1 w-full rounded border px-1 py-1 text-xs dark:border-gray-600 dark:bg-gray-700 dark:text-white"
            placeholder={labels.builderValue}
            value={value}
            onChange={(e) => setValue(e.target.value)}
          />
          {operator === 'BETWEEN' && (
            <input
              className="mb-1 w-full rounded border px-1 py-1 text-xs dark:border-gray-600 dark:bg-gray-700 dark:text-white"
              placeholder={labels.builderValue}
              value={value2}
              onChange={(e) => setValue2(e.target.value)}
            />
          )}
          <select
            className="mb-1 w-full rounded border px-1 py-1 text-[11px] dark:border-gray-600 dark:bg-gray-700 dark:text-white"
            value={mode}
            onChange={(e) => setMode(e.target.value as 'literal' | 'expression')}
          >
            <option value="literal">{labels.builderLiteral}</option>
            <option value="expression">{labels.builderExpression}</option>
          </select>
        </>
      )}
      <div className="flex items-center gap-1">
        <button
          type="button"
          className="flex-1 rounded bg-blue-600 px-1 py-1 text-[11px] font-semibold text-white hover:bg-blue-700"
          onClick={() => onApply(build())}
        >
          {labels.apply}
        </button>
        <button
          type="button"
          className="rounded px-2 py-1 text-[11px] text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700"
          onClick={onClose}
        >
          ✕
        </button>
      </div>
    </div>
  )
}

export default CriteriaGrid
