import { parseCellAddress } from '@bilig/formula';
import { normalizeDefinedName } from '../../workbook-store.js';
import { rewriteFormulaSourceForRenamedStructuredReference } from './structure-structured-ref-rewrite.js';
import { excelCompatibleTableColumnName, normalizeTableColumnName } from './table-column-name-helpers.js';
export function applyTableHeaderRenameForSetCellValue(args) {
    if (!args.serviceArgs.state.workbook.hasTables()) {
        return { formulaChangedCount: args.formulaChangedCount, topologyChanged: args.topologyChanged, value: args.value };
    }
    const header = findTableHeaderCell(args.serviceArgs.state.workbook.listTables(), args.sheetName, args.row, args.col);
    if (!header) {
        return { formulaChangedCount: args.formulaChangedCount, topologyChanged: args.topologyChanged, value: args.value };
    }
    const requestedColumnName = tableColumnNameForLiteral(args.value);
    const nextColumnName = excelCompatibleTableColumnName(requestedColumnName, header.table.columnNames, header.columnIndex);
    const previousColumnName = header.table.columnNames[header.columnIndex] ?? '';
    if (normalizeTableColumnName(previousColumnName) === normalizeTableColumnName(nextColumnName)) {
        return { formulaChangedCount: args.formulaChangedCount, topologyChanged: args.topologyChanged, value: nextColumnName };
    }
    const nextColumnNames = header.table.columnNames.slice();
    nextColumnNames[header.columnIndex] = nextColumnName;
    const nextColumns = header.table.columns?.map((column, index) => index === header.columnIndex ? { ...column, name: nextColumnName } : column);
    args.serviceArgs.state.workbook.setTable({
        ...header.table,
        columnNames: nextColumnNames,
        ...(nextColumns ? { columns: nextColumns } : {}),
    });
    let formulaChangedCount = args.formulaChangedCount;
    let topologyChanged = args.topologyChanged;
    const renamedReference = {
        tableName: header.table.name,
        oldColumnName: previousColumnName,
        newColumnName: nextColumnName,
    };
    const changedDefinedNames = rewriteDefinedNamesForRenamedTableColumn(args.serviceArgs, renamedReference);
    if (changedDefinedNames.size > 0) {
        const reboundCount = formulaChangedCount;
        formulaChangedCount = args.serviceArgs.rebindDefinedNameDependents([...changedDefinedNames], formulaChangedCount);
        topologyChanged = topologyChanged || formulaChangedCount !== reboundCount;
    }
    for (const cellIndex of args.serviceArgs.collectFormulaCellsForTables([header.table.name])) {
        const formula = args.serviceArgs.state.formulas.get(cellIndex);
        if (!formula) {
            continue;
        }
        const source = rewriteFormulaSourceForRenamedStructuredReference(formula.source, renamedReference);
        if (!source || source === formula.source) {
            continue;
        }
        const ownerSheetName = args.serviceArgs.state.workbook.getSheetNameById(args.serviceArgs.state.workbook.cellStore.sheetIds[cellIndex]);
        if (!ownerSheetName) {
            continue;
        }
        const changedTopology = args.serviceArgs.rewriteFormulaSourcePreservingBinding?.(cellIndex, ownerSheetName, source) === true
            ? false
            : args.serviceArgs.bindFormula(cellIndex, ownerSheetName, source);
        formulaChangedCount = args.serviceArgs.markFormulaChanged(cellIndex, formulaChangedCount);
        topologyChanged = topologyChanged || changedTopology;
    }
    return { formulaChangedCount, topologyChanged, value: nextColumnName };
}
export function isTableHeaderCell(tables, sheetName, row, col) {
    return findTableHeaderCell(tables, sheetName, row, col) !== undefined;
}
export function isWorkbookTableHeaderCell(workbook, sheetName, row, col) {
    return workbook.hasTables() && isTableHeaderCell(workbook.listTables(), sheetName, row, col);
}
function rewriteDefinedNamesForRenamedTableColumn(args, renamedReference) {
    const changedNames = new Set();
    for (const record of args.state.workbook.listDefinedNames()) {
        const value = record.value;
        if (typeof value === 'string' && value.startsWith('=')) {
            const source = rewriteFormulaSourceForRenamedStructuredReference(value.slice(1), renamedReference);
            if (!source || `=${source}` === value) {
                continue;
            }
            args.state.workbook.setDefinedName(record.name, `=${source}`, record.scopeSheetName);
            changedNames.add(normalizeDefinedName(record.name));
            continue;
        }
        if (typeof value !== 'object' || value === null) {
            continue;
        }
        switch (value.kind) {
            case 'formula': {
                const formula = value.formula.startsWith('=') ? value.formula.slice(1) : value.formula;
                const source = rewriteFormulaSourceForRenamedStructuredReference(formula, renamedReference);
                if (!source) {
                    break;
                }
                const nextFormula = value.formula.startsWith('=') ? `=${source}` : source;
                if (nextFormula === value.formula) {
                    break;
                }
                args.state.workbook.setDefinedName(record.name, { ...value, formula: nextFormula }, record.scopeSheetName);
                changedNames.add(normalizeDefinedName(record.name));
                break;
            }
            case 'structured-ref':
                if (!structuredReferenceMatches(renamedReference, value.tableName, value.columnName)) {
                    break;
                }
                args.state.workbook.setDefinedName(record.name, { ...value, columnName: renamedReference.newColumnName }, record.scopeSheetName);
                changedNames.add(normalizeDefinedName(record.name));
                break;
            case 'cell-ref':
            case 'range-ref':
            case 'scalar':
                break;
        }
    }
    return changedNames;
}
export function findTableHeaderCell(tables, sheetName, row, col) {
    for (const table of tables) {
        if (table.sheetName !== sheetName || !table.headerRow) {
            continue;
        }
        const start = parseCellAddress(table.startAddress, table.sheetName);
        const end = parseCellAddress(table.endAddress, table.sheetName);
        const headerRow = Math.min(start.row, end.row);
        const startCol = Math.min(start.col, end.col);
        const endCol = Math.max(start.col, end.col);
        if (row === headerRow && col >= startCol && col <= endCol) {
            return { table, columnIndex: col - startCol };
        }
    }
    return undefined;
}
function structuredReferenceMatches(reference, tableName, columnName) {
    return (normalizeTableColumnName(reference.tableName) === normalizeTableColumnName(tableName) &&
        normalizeTableColumnName(reference.oldColumnName) === normalizeTableColumnName(columnName));
}
function tableColumnNameForLiteral(value) {
    if (value === null) {
        return '';
    }
    const name = typeof value === 'boolean' ? (value ? 'TRUE' : 'FALSE') : String(value);
    return name.trim();
}
//# sourceMappingURL=operation-table-header-rename.js.map