'use client';
import { jsx as _jsx } from "react/jsx-runtime";
import { useEffect, useRef, useCallback } from 'react';
import { TabulatorFull as Tabulator } from 'tabulator-tables';
import { cn } from '../../../lib/utils.js';
import './feature-tree-table.css';
// ── Constants ────────────────────────────────────────────────
const STATUS_LABELS = {
    'action-needed': 'Action Needed',
    'in-progress': 'In Progress',
    pending: 'Pending',
    blocked: 'Blocked',
    error: 'Error',
    done: 'Done',
};
/** SVG repo icon — lucide FolderGit2 (16px) */
const REPO_ICON_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/><circle cx="12" cy="13" r="2"/><path d="M14 13h3"/><path d="M7 13h3"/></svg>`;
/** SVG group icon — lucide Layers (16px) */
const GROUP_ICON_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z"/><path d="m22.54 12.43-1.42-.65-8.28 3.78a2 2 0 0 1-1.66 0l-8.28-3.78-1.42.65a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z"/></svg>`;
/** SVG app icon — lucide LayoutGrid (14px) */
const APP_ICON_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect width="7" height="7" x="3" y="3" rx="1"/><rect width="7" height="7" x="14" y="3" rx="1"/><rect width="7" height="7" x="14" y="14" rx="1"/><rect width="7" height="7" x="3" y="14" rx="1"/></svg>`;
// ── Formatters ───────────────────────────────────────────────
function escapeHtml(text) {
    const div = typeof document !== 'undefined' ? document.createElement('div') : null;
    if (div) {
        div.textContent = text;
        return div.innerHTML;
    }
    return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
function statusFormatter(cell) {
    const row = cell.getRow().getData();
    if (row._isGroupHeader)
        return '';
    const value = cell.getValue();
    const label = STATUS_LABELS[value] ?? value;
    return `<span class="status-pill status-pill--${value}"><span class="status-dot"></span>${label}</span>`;
}
function branchFormatter(cell) {
    const row = cell.getRow().getData();
    if (row._isGroupHeader)
        return '';
    const val = cell.getValue();
    if (!val)
        return '';
    return `<code style="font-size:12px;color:var(--color-muted-foreground,#64748b);font-family:var(--font-mono)">${escapeHtml(val)}</code>`;
}
function lifecycleFormatter(cell) {
    const row = cell.getRow().getData();
    if (row._isGroupHeader)
        return '';
    return escapeHtml(cell.getValue());
}
/** Name formatter for non-grouped (flat) rows. Adds an "App" badge when the row is an application. */
function flatNameFormatter(cell) {
    const row = cell.getRow().getData();
    const name = escapeHtml(cell.getValue());
    if (!row._isApplication)
        return name;
    return `<span style="display:inline-flex;align-items:center;gap:8px"><span style="display:inline-flex;align-items:center;gap:4px;padding:1px 6px;border-radius:9999px;background-color:color-mix(in srgb,currentColor 8%,transparent);color:var(--color-muted-foreground,#64748b);font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:0.04em">${APP_ICON_SVG}<span>App</span></span><span>${name}</span></span>`;
}
function repoFormatter(cell) {
    const row = cell.getRow().getData();
    if (row._isGroupHeader)
        return '';
    const val = cell.getValue();
    return `<span style="display:inline-flex;align-items:center;gap:6px">${REPO_ICON_SVG}<span>${escapeHtml(val)}</span></span>`;
}
/** SVG plus icon — lucide Plus (14px) */
const PLUS_ICON_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg>`;
function groupHeaderNameFormatter(groupBy) {
    return (cell) => {
        const row = cell.getRow().getData();
        if (!row._isGroupHeader)
            return flatNameFormatter(cell);
        const icon = groupBy === 'repositoryName' ? REPO_ICON_SVG : GROUP_ICON_SVG;
        const count = row._groupCount ?? 0;
        const countLabel = count === 1 ? '1 item' : `${count} items`;
        const container = document.createElement('span');
        container.style.display = 'inline-flex';
        container.style.alignItems = 'center';
        container.style.gap = '8px';
        container.style.fontWeight = '600';
        container.style.width = '100%';
        container.innerHTML = `${icon}<span>${escapeHtml(row.name)}</span><span style="font-weight:400;color:var(--color-muted-foreground,#64748b);font-size:12px">${countLabel}</span>`;
        // Add repo action buttons and (+) button for repository group headers
        if (groupBy === 'repositoryName' && row._repositoryPath) {
            // Spacer to push actions to the right
            const actionArea = document.createElement('span');
            actionArea.style.marginLeft = 'auto';
            actionArea.style.display = 'inline-flex';
            actionArea.style.alignItems = 'center';
            actionArea.style.gap = '2px';
            actionArea.style.flexShrink = '0';
            // Portal target for React-rendered repo action buttons
            const repoActionsPortal = document.createElement('span');
            repoActionsPortal.setAttribute('data-repo-actions', row._repositoryPath);
            if (row._repositoryId) {
                repoActionsPortal.setAttribute('data-repo-id', row._repositoryId);
            }
            repoActionsPortal.style.display = 'inline-flex';
            repoActionsPortal.style.alignItems = 'center';
            repoActionsPortal.style.gap = '2px';
            actionArea.appendChild(repoActionsPortal);
            // (+) create feature button
            const btn = document.createElement('button');
            btn.className = 'inventory-create-for-repo-btn';
            btn.setAttribute('data-create-for-repo', row._repositoryPath);
            btn.setAttribute('title', 'New feature');
            btn.innerHTML = PLUS_ICON_SVG;
            btn.style.display = 'inline-flex';
            btn.style.alignItems = 'center';
            btn.style.justifyContent = 'center';
            btn.style.width = '24px';
            btn.style.height = '24px';
            btn.style.borderRadius = '4px';
            btn.style.border = 'none';
            btn.style.background = 'transparent';
            btn.style.cursor = 'pointer';
            btn.style.color = 'var(--color-muted-foreground, #64748b)';
            btn.style.flexShrink = '0';
            btn.addEventListener('mouseenter', () => {
                btn.style.background = 'var(--color-accent, #f1f5f9)';
                btn.style.color = 'var(--color-foreground, #0f172a)';
            });
            btn.addEventListener('mouseleave', () => {
                btn.style.background = 'transparent';
                btn.style.color = 'var(--color-muted-foreground, #64748b)';
            });
            actionArea.appendChild(btn);
            container.appendChild(actionArea);
        }
        return container;
    };
}
// ── Actions column ────────────────────────────────────────────
export const ACTIONS_COLUMN_FIELD = '_actions';
const ACTIONS_COLUMN_WIDTH = 48;
/**
 * Tabulator custom formatter for the actions column.
 * Creates a portal target div with data-feature-id for regular rows.
 * Returns empty string for group header rows (no actions on headers).
 */
export function actionsColumnFormatter(cell) {
    const row = cell.getRow().getData();
    if (row._isGroupHeader || row._isRepoGroup)
        return '';
    const container = document.createElement('div');
    if (row._isApplication && row._applicationId) {
        container.setAttribute('data-application-id', row._applicationId);
    }
    else {
        container.setAttribute('data-feature-id', row.id);
    }
    container.style.display = 'flex';
    container.style.alignItems = 'center';
    container.style.justifyContent = 'center';
    container.style.width = '100%';
    container.style.height = '100%';
    return container;
}
/** All possible columns. We'll filter out the grouped-by column in tree mode. */
export function buildColumns({ onRowClick, groupBy }) {
    const clickProps = onRowClick
        ? {
            cellClick: (_e, cell) => {
                const data = cell.getRow().getData();
                if (data._isGroupHeader)
                    return;
                onRowClick(data);
            },
            cssClass: 'cursor-pointer',
        }
        : {};
    const isGrouped = !!groupBy;
    const cols = [
        {
            title: 'Name',
            field: 'name',
            widthGrow: 3,
            headerSort: !isGrouped,
            formatter: isGrouped ? groupHeaderNameFormatter(groupBy) : flatNameFormatter,
            ...clickProps,
        },
        groupBy !== 'repositoryName'
            ? {
                title: 'Repository',
                field: 'repositoryName',
                widthGrow: 2,
                headerSort: !isGrouped,
                formatter: repoFormatter,
            }
            : null,
        groupBy !== 'status'
            ? {
                title: 'Status',
                field: 'status',
                widthGrow: 1.5,
                headerSort: !isGrouped,
                formatter: statusFormatter,
            }
            : null,
        groupBy !== 'lifecycle'
            ? {
                title: 'Lifecycle',
                field: 'lifecycle',
                widthGrow: 1.5,
                headerSort: !isGrouped,
                formatter: lifecycleFormatter,
            }
            : null,
        {
            title: 'Branch',
            field: 'branch',
            widthGrow: 2,
            headerSort: !isGrouped,
            formatter: branchFormatter,
        },
        {
            title: '',
            field: ACTIONS_COLUMN_FIELD,
            width: ACTIONS_COLUMN_WIDTH,
            headerSort: false,
            resizable: false,
            frozen: true,
            formatter: actionsColumnFormatter,
        },
    ];
    return cols.filter(Boolean);
}
// ── Tree builder ─────────────────────────────────────────────
export function displayLabel(groupBy, value) {
    if (groupBy === 'status')
        return STATUS_LABELS[value] ?? value;
    return value;
}
/**
 * Build tree-structured data grouped by repository (legacy format).
 * Each repository becomes a parent node with its features as children.
 * Repos without features are included as empty groups.
 */
export function buildTreeData(flatData, repos) {
    const byRepo = new Map();
    for (const item of flatData) {
        const repoName = item.repositoryName || 'Unknown';
        if (!byRepo.has(repoName))
            byRepo.set(repoName, []);
        byRepo.get(repoName).push(item);
    }
    const repoMeta = new Map();
    if (repos) {
        for (const repo of repos) {
            repoMeta.set(repo.name, { remoteUrl: repo.remoteUrl });
            if (!byRepo.has(repo.name))
                byRepo.set(repo.name, []);
        }
    }
    const roots = [];
    for (const [repoName, features] of byRepo) {
        const lookup = new Map();
        const repoChildren = [];
        for (const item of features)
            lookup.set(item.id, { ...item, _children: [] });
        for (const item of features) {
            const node = lookup.get(item.id);
            if (item.parentId && lookup.has(item.parentId)) {
                lookup.get(item.parentId)._children.push(node);
            }
            else {
                repoChildren.push(node);
            }
        }
        for (const node of lookup.values()) {
            if (node._children?.length === 0)
                delete node._children;
        }
        const remoteUrl = repoMeta.get(repoName)?.remoteUrl ?? features[0]?.remoteUrl;
        roots.push({
            id: `repo-${repoName}`,
            name: repoName,
            status: 'pending',
            lifecycle: '',
            branch: '',
            repositoryName: repoName,
            remoteUrl,
            _isRepoGroup: true,
            _featureCount: features.length,
            ...(repoChildren.length > 0 ? { _children: repoChildren } : {}),
        });
    }
    return roots;
}
export function buildGroupedTree(flatData, groupBy, groupSortDir, itemSortField, itemSortDir) {
    // Group features by field value
    const groups = new Map();
    for (const item of flatData) {
        const key = item[groupBy] || 'Unknown';
        if (!groups.has(key))
            groups.set(key, []);
        groups.get(key).push(item);
    }
    // Sort items within each group
    const sortItems = (items) => [...items].sort((a, b) => {
        const aVal = String(a[itemSortField] ?? '').toLowerCase();
        const bVal = String(b[itemSortField] ?? '').toLowerCase();
        const cmp = aVal.localeCompare(bVal);
        return itemSortDir === 'asc' ? cmp : -cmp;
    });
    // Build group header rows
    const roots = [];
    for (const [key, features] of groups) {
        const sortedChildren = sortItems(features);
        roots.push({
            id: `group-${groupBy}-${key}`,
            name: displayLabel(groupBy, key),
            status: 'pending',
            lifecycle: '',
            branch: '',
            repositoryName: '',
            _isGroupHeader: true,
            _groupCount: features.length,
            _children: sortedChildren,
            // Carry repo info from the first child for create-from-repo and repo actions
            ...(groupBy === 'repositoryName' && features[0]?._repositoryPath
                ? {
                    _repositoryPath: features[0]._repositoryPath,
                    _repositoryId: features[0]._repositoryId,
                }
                : {}),
        });
    }
    // Sort groups
    roots.sort((a, b) => {
        const cmp = a.name.localeCompare(b.name);
        return groupSortDir === 'asc' ? cmp : -cmp;
    });
    return roots;
}
// ── Component ────────────────────────────────────────────────
export function FeatureTreeTable({ data, className, onRowClick, groupBy = null, groupSortDir = 'asc', itemSortField = 'name', itemSortDir = 'asc', onTableRender, onCreateFeatureForRepo, }) {
    const containerRef = useRef(null);
    const tabulatorRef = useRef(null);
    const onRowClickRef = useRef(onRowClick);
    onRowClickRef.current = onRowClick;
    const onTableRenderRef = useRef(onTableRender);
    onTableRenderRef.current = onTableRender;
    const onCreateFeatureForRepoRef = useRef(onCreateFeatureForRepo);
    onCreateFeatureForRepoRef.current = onCreateFeatureForRepo;
    const stableOnRowClick = useCallback((row) => {
        onRowClickRef.current?.(row);
    }, []);
    useEffect(() => {
        if (!containerRef.current)
            return;
        const isGrouped = !!groupBy;
        const columns = buildColumns({ onRowClick: stableOnRowClick, groupBy });
        const tableData = isGrouped
            ? buildGroupedTree(data, groupBy, groupSortDir, itemSortField, itemSortDir)
            : data;
        const container = containerRef.current;
        const table = new Tabulator(container, {
            data: tableData,
            columns,
            layout: 'fitColumns',
            height: '100%',
            placeholder: 'No features found',
            ...(isGrouped
                ? {
                    dataTree: true,
                    dataTreeStartExpanded: false,
                    rowFormatter: (row) => {
                        const rowData = row.getData();
                        if (rowData._isGroupHeader) {
                            row.getElement().classList.add('tabulator-row-repo-group');
                        }
                    },
                }
                : {
                    initialSort: [{ column: 'repositoryName', dir: 'asc' }],
                }),
        });
        table.on('renderComplete', () => {
            onTableRenderRef.current?.(container);
        });
        table.on('tableBuilt', () => {
            onTableRenderRef.current?.(container);
        });
        // Event delegation for (+) create-for-repo buttons in group headers
        const handleCreateClick = (e) => {
            const btn = e.target.closest('[data-create-for-repo]');
            if (!btn)
                return;
            e.stopPropagation();
            const repoPath = btn.getAttribute('data-create-for-repo');
            if (repoPath) {
                onCreateFeatureForRepoRef.current?.(repoPath);
            }
        };
        container.addEventListener('click', handleCreateClick);
        tabulatorRef.current = table;
        return () => {
            container.removeEventListener('click', handleCreateClick);
            table.destroy();
            tabulatorRef.current = null;
        };
    }, [data, stableOnRowClick, groupBy, groupSortDir, itemSortField, itemSortDir]);
    return (_jsx("div", { "data-testid": "feature-tree-table", className: cn('h-full w-full', className), ref: containerRef }));
}
