/**
 * Import/export utilities for the Field Library
 * Handles validation, serialization, and format conversion
 */
import { parse_element } from './element_utils.js';
import { validate_key, format_full_key } from './key_utils.js';
/**
 * Export elements to portable JSON format
 */
export function export_elements(records) {
    return records.map(record => {
        const data = parse_element(record.element);
        return {
            area: record.area,
            key: record.key,
            element: data,
        };
    }).filter(e => e.element !== null);
}
/**
 * Export elements to JSON string
 */
export function export_to_json(records) {
    return JSON.stringify(export_elements(records), null, 2);
}
/**
 * Validate raw JSON input for import
 */
export function validate_import(raw, existing_elements) {
    const errors = [];
    const warnings = [];
    const duplicates = [];
    const elements = [];
    // Must be an array
    if (!Array.isArray(raw)) {
        errors.push({ index: -1, field: 'root', message: 'JSON must be an array of elements' });
        return { valid: false, elements: [], errors, warnings, duplicates };
    }
    if (raw.length === 0) {
        errors.push({ index: -1, field: 'root', message: 'Array is empty' });
        return { valid: false, elements: [], errors, warnings, duplicates };
    }
    // Build set of existing area.key
    const existing_keys = new Set(existing_elements.map(e => format_full_key(e.area, e.key)));
    // Track keys in the import batch for internal duplicates
    const seen_keys = new Set();
    for (let i = 0; i < raw.length; i++) {
        const item = raw[i];
        if (!item || typeof item !== 'object') {
            errors.push({ index: i, field: 'item', message: 'Must be an object' });
            continue;
        }
        // Check required fields: area, key, element
        if (!item.area || typeof item.area !== 'string') {
            errors.push({ index: i, field: 'area', message: 'Missing or invalid "area" (string required)' });
        }
        if (!item.key || typeof item.key !== 'string') {
            errors.push({ index: i, field: 'key', message: 'Missing or invalid "key" (string required)' });
        }
        if (!item.element || typeof item.element !== 'object') {
            errors.push({ index: i, field: 'element', message: 'Missing or invalid "element" (object required)' });
            continue;
        }
        const area = String(item.area || '');
        const key = String(item.key || '');
        // Validate key format
        if (area && !validate_key(area)) {
            errors.push({ index: i, field: 'area', message: `Invalid area "${area}" - only letters, numbers, _, +, -, # allowed` });
        }
        if (key && !validate_key(key)) {
            errors.push({ index: i, field: 'key', message: `Invalid key "${key}" - only letters, numbers, _, +, -, # allowed` });
        }
        // Validate element has field_type
        const element = item.element;
        if (!element.field_type || (element.field_type !== 'field' && element.field_type !== 'group')) {
            errors.push({ index: i, field: 'element.field_type', message: 'element.field_type must be "field" or "group"' });
            continue;
        }
        // Validate field-specific requirements
        if (element.field_type === 'field') {
            if (!element.label) {
                warnings.push(`[${i}] Field "${area}.${key}" has no label`);
            }
        }
        // Validate group-specific requirements
        // Also extract inline fields into separate elements
        const extracted_fields = [];
        if (element.field_type === 'group') {
            if (!element.label) {
                warnings.push(`[${i}] Group "${area}.${key}" has no label`);
            }
            if (element.reference_element && !Array.isArray(element.reference_element)) {
                errors.push({ index: i, field: 'element.reference_element', message: 'reference_element must be an array' });
            }
            // Extract inline fields → separate field elements + convert group to reference_element
            const inline_fields = element.fields;
            if (Array.isArray(inline_fields) && inline_fields.length > 0) {
                const refs = [];
                for (const child of inline_fields) {
                    if (!child || typeof child !== 'object')
                        continue;
                    const child_obj = child;
                    const child_id = String(child_obj.id || child_obj.key || '');
                    if (!child_id) {
                        warnings.push(`[${i}] Skipped inline field with no id`);
                        continue;
                    }
                    // Use the child's id as the key, same area as the group
                    extracted_fields.push({
                        area,
                        key: child_id,
                        element: { ...child_obj, field_type: 'field' },
                    });
                    refs.push({ key: format_full_key(area, child_id) });
                }
                // Convert group: remove inline fields, add reference_element
                element.fields = undefined;
                element.reference_element = [
                    ...(Array.isArray(element.reference_element) ? element.reference_element : []),
                    ...refs,
                ];
                warnings.push(`[${i}] Extracted ${extracted_fields.length} inline field${extracted_fields.length !== 1 ? 's' : ''} from group "${area}.${key}"`);
            }
        }
        // Check for duplicates within the import batch
        const all_to_check = [{ area, key }, ...extracted_fields.map(f => ({ area: f.area, key: f.key }))];
        for (const entry of all_to_check) {
            if (entry.area && entry.key) {
                const full_key = format_full_key(entry.area, entry.key);
                if (seen_keys.has(full_key)) {
                    errors.push({ index: i, field: 'key', message: `Duplicate key "${full_key}" within import data` });
                }
                else {
                    seen_keys.add(full_key);
                }
                // Check for duplicates against existing library
                if (existing_keys.has(full_key)) {
                    duplicates.push(full_key);
                }
            }
        }
        // If no hard errors for this item, add it (and extracted fields)
        const item_errors = errors.filter(e => e.index === i);
        if (item_errors.length === 0) {
            elements.push({
                area,
                key,
                element: element,
            });
            elements.push(...extracted_fields);
        }
    }
    return {
        valid: errors.length === 0,
        elements,
        errors,
        warnings,
        duplicates,
    };
}
/**
 * Download a JSON string as a file
 */
export function download_json(json_string, filename) {
    const blob = new Blob([json_string], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
}
//# sourceMappingURL=import_export.js.map