<?php

declare(strict_types=1);

namespace BadamSoft\WooProductExporter\Helpers;

use DateTimeZone;
use WP_Term;

class Utils {
    public static function sanitize_field_key( $value ): string {
        $value = is_scalar( $value ) ? (string) $value : '';
        $value = trim( $value );

        if ( '' === $value ) {
            return '';
        }

        if ( false !== strpos( $value, '|' ) ) {
            [ $prefix, $raw_key ] = explode( '|', $value, 2 );
            $normalized_prefix     = sanitize_key( $prefix );

            $segments = array_filter( array_map( 'trim', explode( '.', $raw_key ) ), static function ( $segment ) {
                return '' !== $segment;
            } );

            if ( 'attribute' === $normalized_prefix ) {
                $normalized_segments = array_map( 'wc_clean', $segments );
            } else {
                $normalized_segments = array_map( 'sanitize_key', $segments );
            }

            $normalized_segments = array_filter( $normalized_segments, static function ( $segment ) {
                return '' !== $segment;
            } );

            if ( '' === $normalized_prefix ) {
                $normalized_prefix = 'meta';
            }

            $normalized_key = implode( '.', $normalized_segments );

            return $normalized_key ? $normalized_prefix . '|' . $normalized_key : $normalized_prefix;
        }

        return sanitize_key( $value );
    }

    public static function prepare_csv_value( $value ): string {
        if ( is_bool( $value ) ) {
            return $value ? '1' : '0';
        }

        if ( is_array( $value ) ) {
            $value = implode( ', ', array_filter( array_map( 'trim', $value ) ) );
        }

        $value = (string) $value;
        $value = str_replace( [ "\r\n", "\r" ], "\n", $value );

        return trim( $value );
    }

    public static function humanize_attribute_label( string $value ): string {
        $decoded = urldecode( $value );
        $decoded = preg_replace( '/^pa[_-]/i', '', $decoded );
        $decoded = preg_replace( '/^attribute[_-]/i', '', $decoded );
        $decoded = str_replace( [ '_', '-' ], ' ', $decoded );
        $decoded = trim( (string) $decoded );

        if ( '' === $decoded ) {
            return __( 'Attribute', 'badamsoft-product-exporter-for-woocommerce' );
        }

        if ( function_exists( 'mb_convert_case' ) ) {
            $decoded = mb_convert_case( $decoded, MB_CASE_TITLE, 'UTF-8' );
        } else {
            $decoded = ucwords( strtolower( $decoded ) );
        }

        return $decoded;
    }

    public static function humanize_meta_key( string $value ): string {
        $value = trim( $value );

        if ( '' === $value ) {
            return __( 'Meta Field', 'badamsoft-product-exporter-for-woocommerce' );
        }

        $value = ltrim( $value, '_' );
        $value = str_replace( [ '_', '-' ], ' ', $value );
        $value = trim( $value );

        if ( '' === $value ) {
            return __( 'Meta Field', 'badamsoft-product-exporter-for-woocommerce' );
        }

        if ( function_exists( 'mb_convert_case' ) ) {
            $value = mb_convert_case( $value, MB_CASE_TITLE, 'UTF-8' );
        } else {
            $value = ucwords( strtolower( $value ) );
        }

        return $value;
    }

    public static function format_term_with_hierarchy( WP_Term $term ): string {
        $taxonomy = $term->taxonomy;
        $names    = [];

        foreach ( array_reverse( get_ancestors( $term->term_id, $taxonomy ) ) as $ancestor_id ) {
            $ancestor = get_term( $ancestor_id, $taxonomy );

            if ( $ancestor && ! is_wp_error( $ancestor ) ) {
                $names[] = $ancestor->name;
            }
        }

        $names[] = $term->name;

        return implode( ' / ', $names );
    }

    public static function normalize_attribute_identifier( string $key ): string {
        $key = strtolower( $key );

        if ( 0 === strpos( $key, 'attribute_' ) ) {
            $key = substr( $key, strlen( 'attribute_' ) );
        }

        $sanitized = sanitize_key( $key );

        if ( '' === $sanitized ) {
            $sanitized = sanitize_title( $key );
        }

        return $sanitized;
    }

    public static function is_timezone_value_valid( string $value ): bool {
        $value = trim( $value );

        if ( '' === $value ) {
            return false;
        }

        if ( in_array( $value, timezone_identifiers_list(), true ) ) {
            return true;
        }

        if ( 1 === preg_match( '/^[+-]\d{2}:\d{2}$/', $value ) ) {
            return true;
        }

        if ( 1 === preg_match( '/^(?:UTC|GMT)([+-]\d{1,2})(?::?(\d{2}))?$/i', $value ) ) {
            return true;
        }

        if ( 0 === strcasecmp( $value, 'UTC' ) ) {
            return true;
        }

        return false;
    }

    public static function create_timezone( ?string $value = null ): DateTimeZone {
        $value = null === $value ? '' : trim( $value );

        if ( '' === $value ) {
            $value = wp_timezone_string();
        }

        if ( '' === $value ) {
            try {
                return wp_timezone();
            } catch ( \Throwable $exception ) {
                return new DateTimeZone( 'UTC' );
            }
        }

        if ( in_array( $value, timezone_identifiers_list(), true ) ) {
            return new DateTimeZone( $value );
        }

        if ( 0 === strcasecmp( $value, 'UTC' ) ) {
            return new DateTimeZone( 'UTC' );
        }

        if ( 1 === preg_match( '/^[+-]\d{2}:\d{2}$/', $value ) ) {
            return new DateTimeZone( $value );
        }

        if ( preg_match( '/^(?:UTC|GMT)([+-]\d{1,2})(?::?(\d{2}))?$/i', $value, $matches ) ) {
            $hours_raw   = (int) $matches[1];
            $minutes_raw = isset( $matches[2] ) ? (int) $matches[2] : 0;

            $sign        = $hours_raw < 0 ? '-' : '+';
            $hours_abs   = abs( $hours_raw );
            $minutes_abs = abs( $minutes_raw );

            $normalized = sprintf( '%s%02d:%02d', $sign, $hours_abs, $minutes_abs );

            return new DateTimeZone( $normalized );
        }

        try {
            return new DateTimeZone( $value );
        } catch ( \Throwable $exception ) {
            return new DateTimeZone( 'UTC' );
        }
    }
    /**
     * Get timezone string suitable for dropdown selection.
     * For offset-based timezones (like UTC+3), finds a named timezone with the same offset.
     * For named timezones, returns the timezone identifier.
     */
    public static function get_timezone_for_dropdown( ?string $value = null ): string {
        $value = null === $value ? '' : trim( $value );

        if ( '' === $value ) {
            $value = wp_timezone_string();
        }

        if ( '' === $value ) {
            return 'UTC';
        }

        // If it's already a named timezone, return as-is
        if ( in_array( $value, timezone_identifiers_list(), true ) ) {
            return $value;
        }

        if ( 0 === strcasecmp( $value, 'UTC' ) ) {
            return 'UTC';
        }

        // For offset-based values, find a named timezone with the same offset
        $target_offset = null;

        // Parse +03:00 format
        if ( 1 === preg_match( '/^([+-])(\d{2}):(\d{2})$/', $value, $matches ) ) {
            $sign    = $matches[1] === '-' ? -1 : 1;
            $hours   = (int) $matches[2];
            $minutes = (int) $matches[3];
            $target_offset = $sign * ( $hours * 3600 + $minutes * 60 );
        }
        // Parse UTC+3 or GMT+3 format
        elseif ( preg_match( '/^(?:UTC|GMT)([+-]?)(\d{1,2})(?::?(\d{2}))?$/i', $value, $matches ) ) {
            $sign    = ( isset( $matches[1] ) && $matches[1] === '-' ) ? -1 : 1;
            $hours   = (int) $matches[2];
            $minutes = isset( $matches[3] ) ? (int) $matches[3] : 0;
            $target_offset = $sign * ( $hours * 3600 + $minutes * 60 );
        }

        if ( null === $target_offset ) {
            return 'UTC';
        }

        if ( 0 === $target_offset ) {
            return 'UTC';
        }

        // Find a named timezone with matching offset
        $now = new \DateTime( 'now', new \DateTimeZone( 'UTC' ) );
        
        // Preferred regions order (Europe first for +3)
        $preferred_regions = [
            \DateTimeZone::EUROPE,
            \DateTimeZone::ASIA,
            \DateTimeZone::AFRICA,
            \DateTimeZone::AMERICA,
            \DateTimeZone::PACIFIC,
            \DateTimeZone::ATLANTIC,
            \DateTimeZone::INDIAN,
            \DateTimeZone::AUSTRALIA,
            \DateTimeZone::ANTARCTICA,
            \DateTimeZone::ARCTIC,
        ];

        foreach ( $preferred_regions as $region ) {
            $zones = \DateTimeZone::listIdentifiers( $region );
            foreach ( $zones as $zone_name ) {
                $tz = new \DateTimeZone( $zone_name );
                if ( $tz->getOffset( $now ) === $target_offset ) {
                    return $zone_name;
                }
            }
        }

        // Fallback to UTC if no match found
        return 'UTC';
    }
}
