<?php
namespace PrimeLink\Helpers;

if ( ! defined( 'ABSPATH' ) ) { exit; }

/**
 * String helper using Symfony String if available, with fallback to native PHP/WooCommerce.
 */
final class StringHelper {

    /**
     * Check if Symfony String is available (prefixed or normal).
     *
     * @return bool
     */
    private static function has_symfony_string() {
        // Symfony String 6.x requires PHP 8.1+
        if ( version_compare( PHP_VERSION, '8.1.0', '<' ) ) {
            return false;
        }
        
        return class_exists( '\PrimeLink\Vendor\Symfony\Component\String\UnicodeString' ) ||
               class_exists( '\Symfony\Component\String\UnicodeString' );
    }

    /**
     * Get Symfony UnicodeString class.
     *
     * @return string|null
     */
    private static function get_unicode_string_class() {
        if ( class_exists( '\PrimeLink\Vendor\Symfony\Component\String\UnicodeString' ) ) {
            return '\PrimeLink\Vendor\Symfony\Component\String\UnicodeString';
        } elseif ( class_exists( '\Symfony\Component\String\UnicodeString' ) ) {
            return '\Symfony\Component\String\UnicodeString';
        }
        return null;
    }

    /**
     * Create UnicodeString instance.
     *
     * @param string $string String value.
     * @return object|null UnicodeString instance or null.
     */
    private static function create_unicode_string( $string ) {
        $class = self::get_unicode_string_class();
        if ( $class ) {
            return new $class( $string );
        }
        return null;
    }

    /**
     * Convert string to lowercase (Unicode-safe).
     *
     * @param string $string String to convert.
     * @return string Lowercase string.
     */
    public static function lower( $string ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $string );
            if ( $unicode ) {
                return $unicode->lower()->toString();
            }
        }

        // Fallback to native PHP
        return mb_strtolower( $string, 'UTF-8' );
    }

    /**
     * Convert string to uppercase (Unicode-safe).
     *
     * @param string $string String to convert.
     * @return string Uppercase string.
     */
    public static function upper( $string ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $string );
            if ( $unicode ) {
                return $unicode->upper()->toString();
            }
        }

        // Fallback to native PHP
        return mb_strtoupper( $string, 'UTF-8' );
    }

    /**
     * Convert string to title case (Unicode-safe).
     *
     * @param string $string String to convert.
     * @return string Title case string.
     */
    public static function title( $string ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $string );
            if ( $unicode ) {
                return $unicode->title( true )->toString(); // true = all words
            }
        }

        // Fallback to native PHP
        return mb_convert_case( $string, MB_CASE_TITLE, 'UTF-8' );
    }

    /**
     * Convert first character to uppercase (Unicode-safe).
     *
     * @param string $string String to convert.
     * @return string Capitalized string.
     */
    public static function capitalize( $string ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $string );
            if ( $unicode ) {
                return $unicode->title( false )->toString(); // false = first word only
            }
        }

        // Fallback to native PHP
        if ( empty( $string ) ) {
            return $string;
        }
        return mb_strtoupper( mb_substr( $string, 0, 1, 'UTF-8' ), 'UTF-8' ) . mb_substr( $string, 1, null, 'UTF-8' );
    }

    /**
     * Generate a URL-friendly slug from string.
     *
     * @param string $string String to slugify.
     * @param string $separator Separator (default: '-').
     * @return string Slug.
     */
    public static function slugify( $string, $separator = '-' ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $string );
            if ( $unicode ) {
                // Use Symfony's slug method
                $slug = $unicode->ascii()->lower()->toString();
                // Replace non-alphanumeric with separator
                $slug = preg_replace( '/[^a-z0-9]+/', $separator, $slug );
                $slug = trim( $slug, $separator );
                return $slug;
            }
        }

        // Fallback to WooCommerce function
        if ( function_exists( 'sanitize_title' ) ) {
            return sanitize_title( $string );
        }

        // Basic fallback
        $string = self::remove_accents( $string );
        $string = self::lower( $string );
        $string = preg_replace( '/[^a-z0-9]+/', $separator, $string );
        return trim( $string, $separator );
    }

    /**
     * Remove accents/diacritics from string.
     *
     * @param string $string String to process.
     * @return string String without accents.
     */
    public static function remove_accents( $string ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $string );
            if ( $unicode ) {
                return $unicode->ascii()->toString();
            }
        }

        // Fallback to WooCommerce function
        if ( function_exists( 'remove_accents' ) ) {
            return remove_accents( $string );
        }

        // Basic fallback
        return iconv( 'UTF-8', 'ASCII//TRANSLIT//IGNORE', $string );
    }

    /**
     * Truncate string to specified length (Unicode-safe).
     *
     * @param string $string String to truncate.
     * @param int    $length Maximum length.
     * @param string $suffix Suffix to append if truncated.
     * @return string Truncated string.
     */
    public static function truncate( $string, $length, $suffix = '...' ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $string );
            if ( $unicode ) {
                if ( $unicode->length() <= $length ) {
                    return $string;
                }
                return $unicode->slice( 0, $length )->toString() . $suffix;
            }
        }

        // Fallback to native PHP
        if ( mb_strlen( $string, 'UTF-8' ) <= $length ) {
            return $string;
        }
        return mb_substr( $string, 0, $length, 'UTF-8' ) . $suffix;
    }

    /**
     * Get string length (Unicode-safe).
     *
     * @param string $string String to measure.
     * @return int Length.
     */
    public static function length( $string ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $string );
            if ( $unicode ) {
                return $unicode->length();
            }
        }

        // Fallback to native PHP
        return mb_strlen( $string, 'UTF-8' );
    }

    /**
     * Extract substring (Unicode-safe).
     *
     * @param string $string String to extract from.
     * @param int    $start  Start position.
     * @param int|null $length Length (null = to end).
     * @return string Substring.
     */
    public static function slice( $string, $start, $length = null ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $string );
            if ( $unicode ) {
                if ( $length === null ) {
                    return $unicode->slice( $start )->toString();
                }
                return $unicode->slice( $start, $length )->toString();
            }
        }

        // Fallback to native PHP
        if ( $length === null ) {
            return mb_substr( $string, $start, null, 'UTF-8' );
        }
        return mb_substr( $string, $start, $length, 'UTF-8' );
    }

    /**
     * Check if string contains substring (Unicode-safe).
     *
     * @param string $haystack String to search in.
     * @param string $needle  String to search for.
     * @param bool   $case_sensitive Case sensitive search.
     * @return bool True if contains.
     */
    public static function contains( $haystack, $needle, $case_sensitive = true ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $haystack );
            if ( $unicode ) {
                if ( $case_sensitive ) {
                    return $unicode->contains( $needle );
                } else {
                    return $unicode->ignoreCase()->contains( $needle );
                }
            }
        }

        // Fallback to native PHP
        if ( $case_sensitive ) {
            return mb_strpos( $haystack, $needle, 0, 'UTF-8' ) !== false;
        }
        return mb_stripos( $haystack, $needle, 0, 'UTF-8' ) !== false;
    }

    /**
     * Check if string starts with substring (Unicode-safe).
     *
     * @param string $string String to check.
     * @param string $prefix Prefix to check for.
     * @return bool True if starts with.
     */
    public static function starts_with( $string, $prefix ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $string );
            if ( $unicode ) {
                return $unicode->startsWith( $prefix );
            }
        }

        // Fallback to native PHP
        return mb_substr( $string, 0, mb_strlen( $prefix, 'UTF-8' ), 'UTF-8' ) === $prefix;
    }

    /**
     * Check if string ends with substring (Unicode-safe).
     *
     * @param string $string String to check.
     * @param string $suffix Suffix to check for.
     * @return bool True if ends with.
     */
    public static function ends_with( $string, $suffix ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $string );
            if ( $unicode ) {
                return $unicode->endsWith( $suffix );
            }
        }

        // Fallback to native PHP
        $suffix_length = mb_strlen( $suffix, 'UTF-8' );
        if ( $suffix_length === 0 ) {
            return true;
        }
        return mb_substr( $string, -$suffix_length, null, 'UTF-8' ) === $suffix;
    }

    /**
     * Replace occurrences in string (Unicode-safe).
     *
     * @param string|array $search  String(s) to search for.
     * @param string|array $replace String(s) to replace with.
     * @param string       $subject String to search in.
     * @return string Replaced string.
     */
    public static function replace( $search, $replace, $subject ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $subject );
            if ( $unicode ) {
                if ( is_array( $search ) && is_array( $replace ) ) {
                    $result = $subject;
                    foreach ( $search as $index => $search_str ) {
                        $replace_str = isset( $replace[ $index ] ) ? $replace[ $index ] : '';
                        $result = str_replace( $search_str, $replace_str, $result );
                    }
                    return $result;
                } else {
                    return str_replace( $search, $replace, $subject );
                }
            }
        }

        // Fallback to native PHP
        return str_replace( $search, $replace, $subject );
    }

    /**
     * Trim whitespace from string (Unicode-safe).
     *
     * @param string $string String to trim.
     * @param string $chars  Characters to trim (default: whitespace).
     * @return string Trimmed string.
     */
    public static function trim( $string, $chars = " \t\n\r\0\x0B" ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $string );
            if ( $unicode ) {
                return $unicode->trim( $chars )->toString();
            }
        }

        // Fallback to native PHP
        return trim( $string, $chars );
    }

    /**
     * Pad string to specified length (Unicode-safe).
     *
     * @param string $string String to pad.
     * @param int    $length Target length.
     * @param string $pad_string Padding string.
     * @param int    $pad_type STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH.
     * @return string Padded string.
     */
    public static function pad( $string, $length, $pad_string = ' ', $pad_type = STR_PAD_RIGHT ) {
        if ( self::has_symfony_string() ) {
            $unicode = self::create_unicode_string( $string );
            if ( $unicode ) {
                $current_length = $unicode->length();
                if ( $current_length >= $length ) {
                    return $string;
                }

                $pad_length = $length - $current_length;
                $pad = str_repeat( $pad_string, ceil( $pad_length / mb_strlen( $pad_string, 'UTF-8' ) ) );
                $pad = mb_substr( $pad, 0, $pad_length, 'UTF-8' );

                if ( $pad_type === STR_PAD_LEFT ) {
                    return $pad . $string;
                } elseif ( $pad_type === STR_PAD_BOTH ) {
                    $left_pad = mb_substr( $pad, 0, floor( $pad_length / 2 ), 'UTF-8' );
                    $right_pad = mb_substr( $pad, 0, ceil( $pad_length / 2 ), 'UTF-8' );
                    return $left_pad . $string . $right_pad;
                } else {
                    return $string . $pad;
                }
            }
        }

        // Fallback to native PHP
        return str_pad( $string, $length, $pad_string, $pad_type );
    }
}






