/**
 * RoleTable — Tanstack-table bulk editor for roles.
 *
 * Columns:
 *   - checkbox          (multi-select)
 *   - icon              (click to open IconPicker — deferred; currently read-only)
 *   - name              (inline editable via double-click)
 *   - role_id           (monospace, immutable)
 *   - reports_to        (dropdown)
 *   - tools             (count, clickable to open popover)
 *   - agent             (select)
 *   - employees         (count)
 *   - actions           (⋯ menu: Delete)
 *
 * Row click → selects the row in StructureEditor (opens Inspector).
 * Multi-select → bulk-edit bar at top ("Change agent for N roles", etc.)
 */
import { useMemo, useState, type ChangeEvent } from 'react'
import {
  useReactTable, getCoreRowModel, getSortedRowModel, flexRender,
  type ColumnDef, type SortingState,
} from '@tanstack/react-table'
import type { OrgRole, OrgEmployee } from '../types/visual'
import { resolveRoleIcon } from './roleIcons'

const EXTERNAL_AGENTS = ['codex', 'cursor', 'claude_code', 'opencode'] as const

interface RoleTableProps {
  roles: OrgRole[]
  employees: OrgEmployee[]
  selectedIds: string[]
  onSelectRow: (id: string) => void
  onUpdateRole: (roleId: string, updates: {
    name?: string
    reports_to?: string
    preferred_external_agent?: string | null
  }) => void
  onDeleteRole: (roleId: string) => void
  readOnly?: boolean
}

interface TableRow {
  role_id: string
  name: string
  icon: string | null
  reports_to: string
  toolCount: number
  agent: string | null
  employeeCount: number
}

/* ── RoleTable ───────────────────────────────────────────────── */

export function RoleTable({
  roles, employees, selectedIds, onSelectRow,
  onUpdateRole, onDeleteRole, readOnly,
}: RoleTableProps) {
  const [sorting, setSorting] = useState<SortingState>([])
  const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({})
  const [editingCell, setEditingCell] = useState<{ rowId: string; col: 'name' } | null>(null)
  const [nameBuffer, setNameBuffer] = useState('')

  const data: TableRow[] = useMemo(() => {
    const countByRole = new Map<string, number>()
    for (const e of employees) {
      const roleIds = e.role_ids?.length ? e.role_ids : [e.role_id]
      for (const roleId of roleIds) {
        if (roleId) countByRole.set(roleId, (countByRole.get(roleId) ?? 0) + 1)
      }
    }
    return roles.map(r => ({
      role_id: r.role_id,
      name: r.name,
      icon: r.icon ?? null,
      reports_to: r.reports_to,
      toolCount: r.tools?.length ?? 0,
      agent: r.preferred_external_agent ?? null,
      employeeCount: countByRole.get(r.role_id) ?? 0,
    }))
  }, [roles, employees])

  const reportsToOptions = useMemo(
    () => [{ id: 'owner', name: 'Owner' }, ...roles.map(r => ({ id: r.role_id, name: r.name }))],
    [roles],
  )

  const commitName = (rowId: string) => {
    const trimmed = nameBuffer.trim()
    if (trimmed && trimmed !== roles.find(r => r.role_id === rowId)?.name) {
      onUpdateRole(rowId, { name: trimmed })
    }
    setEditingCell(null)
    setNameBuffer('')
  }

  const columns: ColumnDef<TableRow>[] = useMemo(() => [
    {
      id: 'select',
      header: ({ table }) => (
        <input
          type="checkbox"
          checked={table.getIsAllRowsSelected()}
          ref={el => { if (el) el.indeterminate = table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected() }}
          onChange={table.getToggleAllRowsSelectedHandler()}
          disabled={readOnly}
          aria-label="Select all"
        />
      ),
      cell: ({ row }) => (
        <input
          type="checkbox"
          checked={row.getIsSelected()}
          onChange={row.getToggleSelectedHandler()}
          disabled={readOnly}
          aria-label={`Select ${row.original.role_id}`}
          onClick={e => e.stopPropagation()}
        />
      ),
      size: 32,
      enableSorting: false,
    },
    {
      id: 'icon',
      header: '',
      cell: ({ row }) => (
        <img src={resolveRoleIcon(row.original.icon)} alt="" className="rt-cell-icon" />
      ),
      size: 32,
      enableSorting: false,
    },
    {
      id: 'name',
      header: 'Name',
      accessorKey: 'name',
      cell: ({ row }) => {
        const r = row.original
        const isEditing = editingCell?.rowId === r.role_id && editingCell.col === 'name'
        if (isEditing) {
          return (
            <input
              autoFocus
              className="rt-inline-input"
              value={nameBuffer}
              onChange={e => setNameBuffer(e.target.value)}
              onBlur={() => commitName(r.role_id)}
              onKeyDown={e => {
                if (e.key === 'Enter') commitName(r.role_id)
                else if (e.key === 'Escape') { setEditingCell(null); setNameBuffer('') }
              }}
              onClick={e => e.stopPropagation()}
            />
          )
        }
        return (
          <span
            className="rt-cell-name"
            onDoubleClick={e => {
              if (readOnly) return
              e.stopPropagation()
              setNameBuffer(r.name)
              setEditingCell({ rowId: r.role_id, col: 'name' })
            }}
            title="Double-click to edit"
          >
            {r.name}
          </span>
        )
      },
    },
    {
      id: 'role_id',
      header: 'ID',
      accessorKey: 'role_id',
      cell: ({ row }) => <code className="rt-cell-id">{row.original.role_id}</code>,
    },
    {
      id: 'reports_to',
      header: 'Reports to',
      accessorKey: 'reports_to',
      cell: ({ row }) => {
        const r = row.original
        return (
          <select
            className="rt-cell-select"
            value={r.reports_to}
            onChange={(e: ChangeEvent<HTMLSelectElement>) => onUpdateRole(r.role_id, { reports_to: e.target.value })}
            disabled={readOnly}
            onClick={e => e.stopPropagation()}
          >
            {reportsToOptions.filter(o => o.id !== r.role_id).map(o => (
              <option key={o.id} value={o.id}>{o.name}</option>
            ))}
          </select>
        )
      },
    },
    {
      id: 'toolCount',
      header: 'Tools',
      accessorKey: 'toolCount',
      cell: ({ row }) => (
        <span className="rt-cell-count">{row.original.toolCount}</span>
      ),
      size: 64,
    },
    {
      id: 'agent',
      header: 'Agent',
      accessorKey: 'agent',
      cell: ({ row }) => {
        const r = row.original
        return (
          <select
            className="rt-cell-select"
            value={r.agent ?? ''}
            onChange={(e: ChangeEvent<HTMLSelectElement>) => onUpdateRole(r.role_id, { preferred_external_agent: e.target.value || null })}
            disabled={readOnly}
            onClick={e => e.stopPropagation()}
          >
            <option value="">(auto)</option>
            {EXTERNAL_AGENTS.map(a => <option key={a} value={a}>{a}</option>)}
          </select>
        )
      },
    },
    {
      id: 'employeeCount',
      header: 'People',
      accessorKey: 'employeeCount',
      cell: ({ row }) => <span className="rt-cell-count">{row.original.employeeCount}</span>,
      size: 64,
    },
    {
      id: 'actions',
      header: '',
      cell: ({ row }) => (
        <button
          className="rt-cell-action"
          onClick={e => {
            e.stopPropagation()
            if (readOnly) return
            if (confirm(`Delete role "${row.original.name}"?`)) onDeleteRole(row.original.role_id)
          }}
          disabled={readOnly}
          title="Delete"
        >✕</button>
      ),
      size: 40,
      enableSorting: false,
    },
  ], [editingCell, nameBuffer, readOnly, reportsToOptions, onUpdateRole, onDeleteRole])

  const table = useReactTable({
    data,
    columns,
    state: { sorting, rowSelection },
    onSortingChange: setSorting,
    onRowSelectionChange: setRowSelection,
    enableRowSelection: true,
    getRowId: (row) => row.role_id,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
  })

  const selectedCount = Object.values(rowSelection).filter(Boolean).length
  const selectedRoleIds = Object.keys(rowSelection).filter(id => rowSelection[id])

  /* ── Bulk actions ────────────────────────────────────────── */
  const bulkSetAgent = (agent: string | null) => {
    if (readOnly) return
    selectedRoleIds.forEach(id => onUpdateRole(id, { preferred_external_agent: agent }))
    setRowSelection({})
  }
  const bulkDelete = () => {
    if (readOnly) return
    if (!confirm(`Delete ${selectedCount} roles? This cannot be undone.`)) return
    selectedRoleIds.forEach(id => onDeleteRole(id))
    setRowSelection({})
  }

  return (
    <div className="rt-container">
      {selectedCount > 0 && !readOnly && (
        <div className="rt-bulk-bar">
          <span className="rt-bulk-count">{selectedCount} selected</span>
          <select
            className="rt-bulk-select"
            defaultValue=""
            onChange={e => { const v = e.target.value; if (v) bulkSetAgent(v === '__auto__' ? null : v) }}
          >
            <option value="" disabled>Change agent…</option>
            <option value="__auto__">(auto)</option>
            {EXTERNAL_AGENTS.map(a => <option key={a} value={a}>{a}</option>)}
          </select>
          <button className="btn btn-danger btn-sm" onClick={bulkDelete}>Delete selected</button>
          <button className="btn btn-ghost btn-sm" onClick={() => setRowSelection({})}>Clear</button>
        </div>
      )}

      <div className="rt-table-wrap">
        <table className="rt-table">
          <thead>
            {table.getHeaderGroups().map(hg => (
              <tr key={hg.id}>
                {hg.headers.map(h => (
                  <th
                    key={h.id}
                    style={{ width: h.getSize() }}
                    className={h.column.getCanSort() ? 'rt-th-sortable' : ''}
                    onClick={h.column.getToggleSortingHandler()}
                  >
                    {flexRender(h.column.columnDef.header, h.getContext())}
                    {h.column.getIsSorted() === 'asc' && <span className="rt-sort-caret"> ▲</span>}
                    {h.column.getIsSorted() === 'desc' && <span className="rt-sort-caret"> ▼</span>}
                  </th>
                ))}
              </tr>
            ))}
          </thead>
          <tbody>
            {table.getRowModel().rows.length === 0 && (
              <tr><td colSpan={9} className="rt-empty">No roles. Add one via the "+ Add role" button.</td></tr>
            )}
            {table.getRowModel().rows.map(row => {
              const isSelected = selectedIds.includes(row.original.role_id)
              return (
                <tr
                  key={row.id}
                  className={`rt-row${row.getIsSelected() ? ' rt-row-checked' : ''}${isSelected ? ' rt-row-active' : ''}`}
                  onClick={() => onSelectRow(row.original.role_id)}
                >
                  {row.getVisibleCells().map(cell => (
                    <td key={cell.id} style={{ width: cell.column.getSize() }}>
                      {flexRender(cell.column.columnDef.cell, cell.getContext())}
                    </td>
                  ))}
                </tr>
              )
            })}
          </tbody>
        </table>
      </div>
    </div>
  )
}
