/**
 * Schema - Column definition and type system
 * Defines database columns with type safety
 */
const definitionBuilder = (name, type) => {
    return {
        name,
        type,
        nullable: false,
        unique: false,
        primary: false,
        index: false,
    };
};
const createColumnFromDefinition = (definition) => {
    const column = {};
    const enable = (key) => {
        return () => {
            definition[key] = true;
            return column;
        };
    };
    const assign = (key) => {
        return (value) => {
            definition[key] = value;
            return column;
        };
    };
    column.nullable = enable('nullable');
    column.unique = enable('unique');
    column.primary = enable('primary');
    column.index = enable('index');
    column.autoIncrement = enable('autoIncrement');
    column.unsigned = enable('unsigned');
    column.change = enable('change');
    column.drop = enable('drop');
    column.first = enable('first');
    column.default = assign('default');
    column.comment = assign('comment');
    column.references = assign('references');
    column.on = assign('on');
    column.onDelete = assign('onDelete');
    column.onUpdate = assign('onUpdate');
    column.renameTo = assign('renameTo');
    column.after = assign('after');
    column.charset = assign('charset');
    column.collation = assign('collation');
    column.length = assign('length');
    column.precision = assign('precision');
    column.scale = assign('scale');
    column.values = assign('values');
    column.getDefinition = () => ({ ...definition });
    return column;
};
/**
 * Column - Column definition builder
 * Sealed namespace object following Pattern 2
 *
 * @see FRAMEWORK_REFACTOR_FUNCTION_PATTERN.md for Pattern 2 details
 */
export const Column = Object.freeze({
    /**
     * Create a new column instance
     */
    create(name, type) {
        const definition = definitionBuilder(name, type);
        return createColumnFromDefinition(definition);
    },
});
/**
 * Schema - Table definition builder
 * Refactored to Functional Object pattern
 */
/**
 * Create a column proxy to track definition updates
 */
const createColumnProxy = (name, type, columns) => {
    const column = Column.create(name, type);
    columns.set(name, column);
    return column;
};
const SIMPLE_SCHEMA_COLUMN_TYPES = [
    'integer',
    'boolean',
    'date',
    'datetime',
    'json',
    'text',
    'timestamp',
    'uuid',
    'float',
    'double',
    'binary',
    'bigInteger',
    'smallInteger',
    'tinyInteger',
    'mediumInteger',
    'time',
    'year',
    'longText',
    'mediumText',
    'tinyText',
    'blob',
    'mediumBlob',
    'longBlob',
    'tinyBlob',
    'ipAddress',
    'macAddress',
    'geometry',
    'point',
    'lineString',
    'polygon',
    'geometryCollection',
    'multiPoint',
    'multiLineString',
    'multiPolygon',
];
const setSchemaMethod = (target, key, fn) => {
    target[key] = fn;
};
export const Schema = Object.freeze({
    /**
     * Create a new schema instance
     */
    create(table) {
        const columns = new Map();
        const schema = {};
        setSchemaMethod(schema, 'string', (name, length) => {
            const col = createColumnProxy(name, 'string', columns);
            if (length !== undefined)
                col.length(length);
            return col;
        });
        setSchemaMethod(schema, 'decimal', (name, precision, scale) => {
            const col = createColumnProxy(name, 'decimal', columns);
            if (precision !== undefined)
                col.precision(precision);
            if (scale !== undefined)
                col.scale(scale);
            return col;
        });
        setSchemaMethod(schema, 'enum', (name, values) => {
            const col = createColumnProxy(name, 'enum', columns);
            col.values(values);
            return col;
        });
        setSchemaMethod(schema, 'char', (name, length) => {
            const col = createColumnProxy(name, 'char', columns);
            if (length !== undefined)
                col.length(length);
            return col;
        });
        for (const type of SIMPLE_SCHEMA_COLUMN_TYPES) {
            setSchemaMethod(schema, type, (name) => createColumnProxy(name, type, columns));
        }
        setSchemaMethod(schema, 'increments', (name) => createColumnProxy(name, 'integer', columns).primary().autoIncrement());
        setSchemaMethod(schema, 'bigIncrements', (name) => createColumnProxy(name, 'bigInteger', columns).primary().autoIncrement());
        setSchemaMethod(schema, 'timestamps', () => {
            createColumnProxy('created_at', 'timestamp', columns).nullable();
            createColumnProxy('updated_at', 'timestamp', columns).nullable();
        });
        setSchemaMethod(schema, 'softDeletes', () => {
            createColumnProxy('deleted_at', 'timestamp', columns).nullable();
        });
        setSchemaMethod(schema, 'getColumns', () => columns);
        setSchemaMethod(schema, 'getTable', () => table);
        return schema;
    },
});
