/**
 * Custom PostgreSQL array types for Drizzle ORM
 * Matches Sequelize's ARRAY(DataTypes.XXX) functionality
 */
import { customType } from 'drizzle-orm/pg-core';
/**
 * Helper function to safely parse array values from driver
 * Handles: null, undefined, empty string, already-parsed arrays, and string representations
 */
function parseArrayValue(value, mapper) {
    // Handle null/undefined
    if (value == null)
        return [];
    // Already an array (driver already parsed it)
    if (Array.isArray(value)) {
        return value.map(v => {
            if (v == null)
                return v;
            return mapper(String(v));
        });
    }
    // Not a string - try to convert
    if (typeof value !== 'string') {
        return [];
    }
    // Empty array representation
    if (value === '{}' || value === '')
        return [];
    // Parse string representation like "{1,2,3}"
    return value.replace(/[{}]/g, '').split(',').map(mapper);
}
/**
 * Helper function specifically for boolean arrays
 * Handles various boolean representations from PostgreSQL
 */
function parseBooleanArrayValue(value) {
    // Handle null/undefined
    if (value == null)
        return [];
    // Already an array
    if (Array.isArray(value)) {
        return value.map(v => {
            if (v == null)
                return false;
            if (typeof v === 'boolean')
                return v;
            const str = String(v).toLowerCase();
            return str === 't' || str === 'true' || str === '1';
        });
    }
    // Not a string
    if (typeof value !== 'string') {
        return [];
    }
    // Empty array
    if (value === '{}' || value === '')
        return [];
    // Parse string representation
    return value.replace(/[{}]/g, '').split(',').map(v => {
        const str = v.toLowerCase();
        return str === 't' || str === 'true' || str === '1';
    });
}
/**
 * Helper for text arrays that need quote handling
 */
function parseTextArrayValue(value) {
    // Handle null/undefined
    if (value == null)
        return [];
    // Already an array
    if (Array.isArray(value)) {
        return value.map(v => v == null ? '' : String(v));
    }
    // Not a string
    if (typeof value !== 'string') {
        return [];
    }
    // Empty array
    if (value === '{}' || value === '')
        return [];
    // Parse string representation
    return value.replace(/^{|}$/g, '').split(',').map(v => v.replace(/^"|"$/g, '').replace(/\\"/g, '"'));
}
/**
 * Array of integers
 * Usage: arrayInteger('tags')
 */
export const arrayInteger = (name) => customType({
    dataType() {
        return 'integer[]';
    },
    toDriver(value) {
        return `{${value.join(',')}}`;
    },
    fromDriver(value) {
        return parseArrayValue(value, Number);
    },
})(name);
/**
 * Array of big integers
 * Usage: arrayBigInt('large_numbers')
 */
export const arrayBigInt = (name) => customType({
    dataType() {
        return 'bigint[]';
    },
    toDriver(value) {
        return `{${value.join(',')}}`;
    },
    fromDriver(value) {
        return parseArrayValue(value, BigInt);
    },
})(name);
/**
 * Array of strings/text
 * Usage: arrayText('labels')
 */
export const arrayText = (name) => customType({
    dataType() {
        return 'text[]';
    },
    toDriver(value) {
        // Escape special characters and quotes
        const escaped = value.map(v => `"${v.replace(/"/g, '\\"')}"`);
        return `{${escaped.join(',')}}`;
    },
    fromDriver(value) {
        return parseTextArrayValue(value);
    },
})(name);
/**
 * Array of varchar (alias for arrayText for compatibility)
 * Usage: arrayVarchar('names')
 */
export const arrayVarchar = arrayText;
/**
 * Array of UUIDs
 * Usage: arrayUuid('user_ids')
 */
export const arrayUuid = (name) => customType({
    dataType() {
        return 'uuid[]';
    },
    toDriver(value) {
        return `{${value.join(',')}}`;
    },
    fromDriver(value) {
        return parseArrayValue(value, String);
    },
})(name);
/**
 * Array of booleans
 * Usage: arrayBoolean('flags')
 */
export const arrayBoolean = (name) => customType({
    dataType() {
        return 'boolean[]';
    },
    toDriver(value) {
        return `{${value.join(',')}}`;
    },
    fromDriver(value) {
        return parseBooleanArrayValue(value);
    },
})(name);
/**
 * Array of decimals/numeric
 * Usage: arrayDecimal('prices')
 */
export const arrayDecimal = (name) => customType({
    dataType() {
        return 'decimal[]';
    },
    toDriver(value) {
        return `{${value.join(',')}}`;
    },
    fromDriver(value) {
        return parseArrayValue(value, Number);
    },
})(name);
/**
 * Array of double precision
 * Usage: arrayDouble('coordinates')
 */
export const arrayDouble = (name) => customType({
    dataType() {
        return 'double precision[]';
    },
    toDriver(value) {
        return `{${value.join(',')}}`;
    },
    fromDriver(value) {
        return parseArrayValue(value, Number);
    },
})(name);
/**
 * Array of timestamps with timezone
 * Usage: arrayDateTimeTz('event_times')
 */
export const arrayDateTimeTz = (name) => customType({
    dataType() {
        return 'timestamptz[]';
    },
    toDriver(value) {
        const timestamps = value.map(d => {
            if (d instanceof Date)
                return d.toISOString();
            if (typeof d === 'string')
                return new Date(d).toISOString();
            return String(d);
        });
        return `{${timestamps.join(',')}}`;
    },
    fromDriver(value) {
        return parseArrayValue(value, v => new Date(v));
    },
})(name);
/**
 * Array of timestamps without timezone (legacy)
 * Usage: arrayDateTime('event_dates')
 */
export const arrayDateTime = (name) => customType({
    dataType() {
        return 'timestamp[]';
    },
    toDriver(value) {
        const timestamps = value.map(d => {
            if (d instanceof Date)
                return d.toISOString();
            if (typeof d === 'string')
                return new Date(d).toISOString();
            return String(d);
        });
        return `{${timestamps.join(',')}}`;
    },
    fromDriver(value) {
        return parseArrayValue(value, v => new Date(v));
    },
})(name);
/**
 * Array of dates (timestamps) - alias for arrayDateTime for backwards compatibility
 * Usage: arrayDate('event_dates')
 */
export const arrayDate = arrayDateTime;
/**
 * Array of date only (no time)
 * Usage: arrayDateOnly('birthdays')
 */
export const arrayDateOnly = (name) => customType({
    dataType() {
        return 'date[]';
    },
    toDriver(value) {
        return `{${value.join(',')}}`;
    },
    fromDriver(value) {
        return parseArrayValue(value, String);
    },
})(name);
/**
 * Array of time with timezone
 * Usage: arrayTimeTz('schedule_times')
 */
export const arrayTimeTz = (name) => customType({
    dataType() {
        return 'timetz[]';
    },
    toDriver(value) {
        return `{${value.join(',')}}`;
    },
    fromDriver(value) {
        return parseArrayValue(value, String);
    },
})(name);
/**
 * Array of time without timezone (legacy)
 * Usage: arrayTime('schedule_times')
 */
export const arrayTime = (name) => customType({
    dataType() {
        return 'time[]';
    },
    toDriver(value) {
        return `{${value.join(',')}}`;
    },
    fromDriver(value) {
        return parseArrayValue(value, String);
    },
})(name);
/**
 * Generic array type for custom types
 * Usage: arrayOf('custom_type[]', 'field')
 */
export const arrayOf = (arrayType, name) => customType({
    dataType() {
        return arrayType;
    },
    toDriver(value) {
        if (Array.isArray(value)) {
            return `{${value.join(',')}}`;
        }
        return value;
    },
    fromDriver(value) {
        return parseArrayValue(value, v => v);
    },
})(name);
//# sourceMappingURL=arrays.js.map