<?php
/**
 * Helper utilities for storing and normalizing custom field rules.
 *
 * @package WPR_Translate
 */
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}
/**
 * Normalize raw rules into a consistent structure.
 */
function wpr_translate_normalize_custom_field_rules( $raw_rules ) {
    $rules = array();
    if ( ! is_array( $raw_rules ) ) {
        return $rules;
    }
    $allowed_actions = array( 'copy', 'translate', 'copy-once', 'ignore' );
    foreach ( $raw_rules as $key => $entry ) {
        $rule = array();
        if ( is_array( $entry ) ) {
            $rule = $entry;
            if ( ! isset( $rule['id'] ) && ! isset( $rule['key'] ) && ! is_numeric( $key ) ) {
                $rule['id'] = $key;
            }
        } elseif ( ! is_numeric( $key ) ) {
            $rule = array(
                'id'     => $key,
                'action' => $entry,
            );
        }
        if ( empty( $rule ) || ! is_array( $rule ) ) {
            continue;
        }
        // Normalize the rule identifier.
        $id = isset( $rule['id'] ) ? $rule['id'] : ( isset( $rule['key'] ) ? $rule['key'] : '' );
        $id = sanitize_text_field( $id );
        if ( '' === $id ) {
            continue;
        }
        // Support both the legacy `action` key and the newer `value` key from
        // the JSON configuration file when determining the desired behavior.
        $raw_action = '';
        if ( isset( $rule['action'] ) ) {
            $raw_action = $rule['action'];
        } elseif ( isset( $rule['value'] ) ) {
            $raw_action = $rule['value'];
        }
        // Sanitize and validate the action.
        $action     = sanitize_key( $raw_action );
        if ( ! in_array( $action, $allowed_actions, true ) ) {
            $action = 'copy';
        }
        $post_type  = isset( $rule['post'] ) ? sanitize_key( $rule['post'] ) : '';
        // Build a unique key per post type to avoid collisions.
        $unique_key = wpr_translate_build_unique_rule_id( $id, $post_type, $rules );
        $rules[ $unique_key ] = array(
            'id'          => $id,
            'uid'         => $unique_key,
            'label'       => isset( $rule['label'] ) ? sanitize_text_field( $rule['label'] ) : $id,
            'description' => isset( $rule['description'] ) ? sanitize_text_field( $rule['description'] ) : '',
            'action'      => $action,
            'post'        => $post_type,
        );
    }
    return wpr_translate_group_custom_field_rules_by_post( $rules );
}
/**
 * Build a unique rule identifier per post type so duplicate field keys do not collide.
 */
function wpr_translate_build_unique_rule_id( $field_id, $post_type, $existing_rules ) {
    // Compose a base ID that includes the post type when available.
    $base_id   = '' !== $post_type ? $post_type . '__' . $field_id : $field_id;
    $unique_id = $base_id;
    $counter   = 2;
    while ( isset( $existing_rules[ $unique_id ] ) ) {
        // Append an incrementing suffix until unique.
        $unique_id = $base_id . '-' . $counter;
        $counter++;
    }
    return $unique_id;
}
/**
 * Group custom field rules by post type, prioritizing estate properties.
 * @param array $rules Custom field rules keyed by identifier.
 * @return array
 */
function wpr_translate_group_custom_field_rules_by_post( $rules ) {
    $grouped_rules = array();
    if ( ! is_array( $rules ) ) {
        return $grouped_rules;
    }
    $post_order = array();
    foreach ( $rules as $id => $rule ) {
        if ( ! is_array( $rule ) ) {
            continue;
        }
        $post_type = isset( $rule['post'] ) ? sanitize_key( $rule['post'] ) : '';
        if ( ! isset( $grouped_rules[ $post_type ] ) ) {
            $grouped_rules[ $post_type ] = array();
            $post_order[]               = $post_type;
        }
        // Rebuild the unique ID per post type if missing.
        $base_rule_id = isset( $rule['id'] ) ? $rule['id'] : $id;
        $unique_id    = isset( $rule['uid'] ) ? $rule['uid'] : wpr_translate_build_unique_rule_id( $base_rule_id, $post_type, $grouped_rules[ $post_type ] );
        $rule['uid']  = $unique_id;
        $grouped_rules[ $post_type ][ $unique_id ] = $rule;
    }
    $ordered_rules = array();
    // Ensure estate_property rules are listed first.
    if ( isset( $grouped_rules['estate_property'] ) ) {
        foreach ( $grouped_rules['estate_property'] as $rule_id => $rule ) {
            $ordered_rules[ $rule_id ] = $rule;
        }
    }
    foreach ( $post_order as $post_type ) {
        if ( 'estate_property' === $post_type ) {
            continue;
        }
        // Append remaining post types in discovery order.
        foreach ( $grouped_rules[ $post_type ] as $rule_id => $rule ) {
            $ordered_rules[ $rule_id ] = $rule;
        }
    }
    return $ordered_rules;
}
/**
 * Convert raw custom field configuration into normalized rule entries.
 *
 * @param array $custom_fields Custom field definitions provided by the theme.
 *
 * @return array
 */
function wpr_translate_convert_legacy_custom_fields_to_rules( $custom_fields ) {
    $legacy_rules = array();
    if ( empty( $custom_fields ) || ! is_array( $custom_fields ) ) {
        return $legacy_rules;
    }
    foreach ( $custom_fields as $field ) {
        // Each entry should be an array with the expected indexes; skip invalid items.
        if ( ! is_array( $field ) ) {
            continue;
        }
        // Index 0 stores the raw field name which becomes the meta key.
        $raw_name = isset( $field[0] ) ? $field[0] : '';
        if ( '' === $raw_name ) {
            continue;
        }
        // Sanitize the meta key used for rule identification.
        $meta_key = ( $raw_name );
        if ( '' === $meta_key ) {
            continue;
        }
        // Index 1 holds the display label that should appear in the admin table.
        $label = isset( $field[1] ) ? sanitize_text_field( $field[1] ) : $meta_key;
        // Indexes 2-4 can contain type, order, and dropdown values; capture a short summary.
        $type_value    = isset( $field[2] ) ? sanitize_text_field( $field[2] ) : '';
        $choice_values = isset( $field[4] ) ? sanitize_text_field( $field[4] ) : '';
        $description_parts = array();
        if ( '' !== $type_value ) {
            $description_parts[] = sprintf(
                /* translators: %s: Field type defined in the theme options. */
                esc_html__( 'Type: %s', 'wpr-translate' ),
                $type_value
            );
        }
        if ( '' !== $choice_values ) {
            $description_parts[] = sprintf(
                /* translators: %s: Dropdown values defined in the theme options. */
                esc_html__( 'Values: %s', 'wpr-translate' ),
                $choice_values
            );
        }
        // Prepare the description that will appear below the label in the rule list.
        $description = '';
        if ( ! empty( $description_parts ) ) {
            $description = sanitize_text_field( implode( ' | ', $description_parts ) );
        }
        // Store the normalized legacy rule.
        $legacy_rules[ $meta_key ] = array(
            'id'          => $meta_key,
            'label'       => $label,
            'description' => $description,
            'action'      => 'copy',
            'post'        => 'estate_property',
        );
    }
    return $legacy_rules;
}
/**
 * Persist the latest rules loaded from disk.
 */
function wpr_translate_store_custom_field_rules_defaults( $rules, $hash, $path, $timestamp ) {
    $allowed = array( 'copy', 'translate', 'copy-once', 'ignore' );
    $sanitized_rules = array();
    // Legacy theme field rule import has been removed.
    $legacy_rules = array();
    if ( ! empty( $legacy_rules ) ) {
        foreach ( $legacy_rules as $legacy_id => $legacy_rule ) {
            if ( ! is_array( $legacy_rule ) ) {
                continue;
            }
            $rule_id   = isset( $legacy_rule['id'] ) ? sanitize_text_field( $legacy_rule['id'] ) : sanitize_text_field( $legacy_id );
            $post_type = isset( $legacy_rule['post'] ) ? sanitize_key( $legacy_rule['post'] ) : 'estate_property';
            if ( '' === $rule_id ) {
                continue;
            }
            $action = isset( $legacy_rule['action'] ) ? sanitize_key( $legacy_rule['action'] ) : 'copy';
            if ( ! in_array( $action, $allowed, true ) ) {
                $action = 'copy';
            }
            // Ensure a unique key when storing the rule.
            $unique_id                  = wpr_translate_build_unique_rule_id( $rule_id, $post_type, $sanitized_rules );
            $sanitized_rules[ $unique_id ] = array(
                'id'          => $rule_id,
                'uid'         => $unique_id,
                'label'       => isset( $legacy_rule['label'] ) ? sanitize_text_field( $legacy_rule['label'] ) : $rule_id,
                'description' => isset( $legacy_rule['description'] ) ? sanitize_text_field( $legacy_rule['description'] ) : '',
                'action'      => $action,
                'post'        => $post_type,
            );
        }
    }
    $combined_rules = is_array( $legacy_rules ) ? $legacy_rules : array();
    // Merge the JSON rules after the legacy entries so both data sources are stored together.
    if ( is_array( $rules ) ) {
        foreach ( $rules as $id => $rule ) {
            $combined_rules[ $id ] = $rule;
        }
    }
    // Sanitize each merged rule before storing it to the database.
    foreach ( $combined_rules as $id => $rule ) {
        if ( ! is_array( $rule ) ) {
            continue;
        }
        $rule_id = isset( $rule['id'] ) ? sanitize_text_field( $rule['id'] ) : sanitize_text_field( $id );
        if ( '' === $rule_id ) {
            continue;
        }
        $post_type = isset( $rule['post'] ) ? sanitize_key( $rule['post'] ) : '';
        $action = isset( $rule['action'] ) ? sanitize_key( $rule['action'] ) : 'copy';
        if ( ! in_array( $action, $allowed, true ) ) {
            $action = 'copy';
        }
        // Build the unique key for the stored rule.
        $unique_id                      = wpr_translate_build_unique_rule_id( $rule_id, $post_type, $sanitized_rules );
        $sanitized_rules[ $unique_id ] = array(
            'id'          => $rule_id,
            'uid'         => $unique_id,
            'label'       => isset( $rule['label'] ) ? sanitize_text_field( $rule['label'] ) : $rule_id,
            'description' => isset( $rule['description'] ) ? sanitize_text_field( $rule['description'] ) : '',
            'action'      => $action,
            'post'        => $post_type,
        );
    }
    // Group rules by post type before storing.
    $sanitized_rules = wpr_translate_group_custom_field_rules_by_post( $sanitized_rules );
    // Store the defaults along with file metadata.
    update_option(
        'wpr_cf_rules_defaults',
        array(
            'rules'       => $sanitized_rules,
            'hash'        => sanitize_text_field( $hash ),
            'path'        => sanitize_text_field( $path ),
            'last_loaded' => absint( $timestamp ),
        )
    );
}
/**
 * Retrieve the stored defaults from the database.
 */
function wpr_translate_get_stored_custom_field_rules_defaults() {
    $stored = get_option( 'wpr_cf_rules_defaults', array() );
    if ( ! is_array( $stored ) ) {
        $stored = array();
    }
    $rules = array();
    if ( isset( $stored['rules'] ) && is_array( $stored['rules'] ) ) {
        // Normalize stored rules to ensure consistent structure.
        $rules = wpr_translate_normalize_custom_field_rules( $stored['rules'] );
    }
    // Legacy theme field rule import has been removed.
    $legacy_rules = array();
    if ( ! empty( $legacy_rules ) ) {
        // Remove stored duplicates that would be overridden by legacy rules.
        foreach ( $legacy_rules as $legacy_id => $legacy_rule ) {
            foreach ( $rules as $stored_key => $stored_rule ) {
                $stored_post = isset( $stored_rule['post'] ) ? $stored_rule['post'] : '';
                if ( $legacy_id === ( isset( $stored_rule['id'] ) ? $stored_rule['id'] : '' ) && ( '' === $stored_post || $stored_post === $legacy_rule['post'] ) ) {
                    unset( $rules[ $stored_key ] );
                }
            }
        }
        $rules = array_merge( $legacy_rules, $rules );
    }
    // Return normalized defaults with metadata.
    return array(
        'rules'       => $rules,
        'hash'        => isset( $stored['hash'] ) ? sanitize_text_field( $stored['hash'] ) : '',
        'path'        => isset( $stored['path'] ) ? sanitize_text_field( $stored['path'] ) : wpr_translate_get_custom_field_rules_file_path(),
        'last_loaded' => isset( $stored['last_loaded'] ) ? absint( $stored['last_loaded'] ) : 0,
    );
}
