<?php
/**
 * Variable to String Converter Utility
 *
 * Provides consistent and safe conversion of any variable type to string
 * for use in AI prompts and template replacements.
 *
 * @package AI_Product_Tools
 * @subpackage Utils
 * @since 2.4.1
 */

namespace AIPT\Utils;

/**
 * Class VariableConverter
 *
 * Handles conversion of various data types (arrays, objects, null, etc.)
 * to safe string representations for prompt generation.
 */
class VariableConverter {

    /**
     * Convert any value to a safe string representation
     *
     * Handles:
     * - Arrays (indexed or associative)
     * - Null values
     * - Booleans
     * - Numbers
     * - Objects (with __toString or converted to JSON)
     * - Already-string values (returned as-is)
     *
     * @param mixed $value The value to convert
     * @param string $emptyDefault Default string for empty/null values
     * @return string Safe string representation
     */
    public static function toString($value, string $emptyDefault = ''): string {

        if ($value === null) {
            return $emptyDefault;
        }

        if (is_bool($value)) {
            return $value ? 'Yes' : 'No';
        }

        if (is_array($value)) {

            if (empty($value)) {
                return $emptyDefault;
            }

            if (self::isAssociativeArray($value)) {
                return self::formatKeyValueArray($value);
            } else {
                return self::formatList($value);
            }
        }

        if (is_object($value)) {

            if (method_exists($value, '__toString')) {
                return (string) $value;
            }

            if ($value instanceof \stdClass) {
                return wp_json_encode($value, JSON_UNESCAPED_UNICODE);
            }

            return get_class($value);
        }

        return (string) $value;
    }

    /**
     * Format an associative array as "key: value, key: value"
     *
     * @param array $array Associative array to format
     * @param string $separator Separator between items (default: ', ')
     * @param string $keyValueSeparator Separator between key and value (default: ': ')
     * @return string Formatted string
     */
    public static function formatKeyValueArray(array $array, string $separator = ', ', string $keyValueSeparator = ': '): string {
        if (empty($array)) {
            return '';
        }

        $parts = [];
        foreach ($array as $key => $value) {

            $valueStr = self::toString($value);
            if ($valueStr !== '') {
                $parts[] = $key . $keyValueSeparator . $valueStr;
            }
        }

        return implode($separator, $parts);
    }

    /**
     * Format an indexed array as a comma-separated list
     *
     * @param array $array Indexed array to format
     * @param string $separator Separator between items (default: ', ')
     * @return string Comma-separated string
     */
    public static function formatList(array $array, string $separator = ', '): string {
        if (empty($array)) {
            return '';
        }

        $stringValues = array_map(function($value) {
            return self::toString($value);
        }, $array);

        $stringValues = array_filter($stringValues, function($value) {
            return $value !== '';
        });

        return implode($separator, $stringValues);
    }

    /**
     * Batch convert an array of variables for str_replace() or similar operations
     *
     * Takes an array of [placeholder => value] and returns [placeholder => safeString]
     *
     * @param array $variables Map of placeholder => mixed value
     * @param string $emptyDefault Default for empty values
     * @return array Map of placeholder => string value
     */
    public static function convertVariables(array $variables, string $emptyDefault = ''): array {
        $converted = [];

        foreach ($variables as $placeholder => $value) {
            $converted[$placeholder] = self::toString($value, $emptyDefault);
        }

        return $converted;
    }

    /**
     * Check if an array is associative (has string keys)
     *
     * @param array $array Array to check
     * @return bool True if associative, false if indexed
     */
    private static function isAssociativeArray(array $array): bool {
        if (empty($array)) {
            return false;
        }

        return array_keys($array) !== range(0, count($array) - 1);
    }

    /**
     * Format product attributes specifically
     *
     * Helper method for WooCommerce product attributes
     *
     * @param mixed $attributes Product attributes (array or string)
     * @return string Formatted attributes string
     */
    public static function formatProductAttributes($attributes): string {
        if (is_string($attributes)) {
            return $attributes;
        }

        if (!is_array($attributes) || empty($attributes)) {
            return '';
        }

        $formatted = [];
        foreach ($attributes as $key => $value) {

            if (is_array($value)) {
                $valueStr = implode(', ', $value);
            } else {
                $valueStr = (string) $value;
            }

            if ($valueStr !== '') {
                $formatted[] = $key . ': ' . $valueStr;
            }
        }

        return implode(', ', $formatted);
    }

    /**
     * Format custom variables from ACF, post meta, etc.
     *
     * @param mixed $value Custom field value (could be anything)
     * @param string $fieldType Optional field type hint for better formatting
     * @return string Formatted value
     */
    public static function formatCustomField($value, string $fieldType = ''): string {

        switch ($fieldType) {
            case 'date':
            case 'datetime':
                if (is_numeric($value)) {
                    return gmdate('Y-m-d', $value);
                }
                break;

            case 'wysiwyg':
            case 'textarea':

                return wp_strip_all_tags($value);

            case 'select':
            case 'checkbox':
            case 'radio':

                if (is_array($value)) {
                    return self::formatList($value);
                }
                break;
        }

        return self::toString($value);
    }
}
