<?php

namespace Fab\Plugin\Helper;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Helper library for Fab plugins
 *
 * @package    Fab
 * @subpackage Fab\Includes
 */

trait Location {

    /**
     * Normalize grouped FAB location types into a flat array of location definitions.
     *
     * @param array $grouped_location_types The grouped FAB location types.
     * @return array Flattened array of location type definitions.
     */
    private function _normalize_fab_location_types( array $grouped_location_types ) {
        $normalized = array();

        foreach ( $grouped_location_types as $group ) {
            if ( isset( $group['children'] ) && is_array( $group['children'] ) ) {
                foreach ( $group['children'] as $child ) {
                    if ( isset( $child['id'] ) ) {
                        $normalized[ $child['id'] ] = $child;
                    }
                }
            }
        }

        return $normalized;
    }

    /**
     * Format the condition value for display based on the label context.
     *
     * This method formats values such as price, date, day, or month
     * into a more human-readable and translatable format based on the label's keyword.
     *
     * @param string $label The condition label (e.g. "Sale Price", "Date").
     * @param mixed  $value The original condition value to be formatted.
     * @return string The formatted value for display.
     */
    private function _format_condition_value( $label, $value ) {
        $label_lower = strtolower( $label );

        if ( strpos( $label_lower, 'price' ) !== false || strpos( $label_lower, 'subtotal' ) !== false || strpos( $label_lower, 'spend' ) !== false ) {
            // Format as currency using WooCommerce wc_price or fallback.
            return function_exists( 'wc_price' )
                ? wp_strip_all_tags( wc_price( floatval( $value ) ) )
                // translators: %s: The numeric value formatted as currency.
                : wp_kses_post( sprintf( __( '$%s', 'floating-awesome-button' ), number_format( floatval( $value ), 2 ) ) );
        }

        if ( strpos( $label_lower, 'date' ) !== false ) {
            // Format full date using WordPress i18n-aware format.
            $timestamp = strtotime( $value );
            if ( $timestamp ) {
                return date_i18n( get_option( 'date_format' ), $timestamp );
            }
        }

        if ( strpos( $label_lower, 'day' ) !== false && is_numeric( $value ) && $value >= 0 && $value <= 6 ) {
            // Convert numeric day (0 = Sunday) to localized day name.
            $timestamp = strtotime( "Sunday +{$value} days" ); // 0 = Sunday
            return date_i18n( 'l', $timestamp ); // 'l' = full day name
        }

        if ( strpos( $label_lower, 'month' ) !== false && is_numeric( $value ) && $value >= 1 && $value <= 12 ) {
            // Convert numeric month to localized month name.
            $timestamp = strtotime( '2000-' . str_pad( $value, 2, '0', STR_PAD_LEFT ) . '-01' );
            return date_i18n( 'F', $timestamp ); // 'F' = full month name.
        }

        return $value;
    }

    /**
     * Generate condition text based on label, operator, and value.
     *
     * @param string $label    The subject label (e.g., "The date").
     * @param string $operator The operator (e.g., '>', '=', '<=').
     * @param string $value    The formatted value.
     * @return string
     */
    private function _build_condition_description( $label, $operator, $value ) {
        // Normalize '=' to '=='.
        if ( '=' === $operator ) {
            $operator = '==';
        }

        // Get all operator definitions.
        $all_operators = \Fab\Metabox\FABMetaboxLocation::get_all_operators();

        // Build translation map based on operator ID.
        $operator_messages = array();

        foreach ( $all_operators as $id => $data ) {
            switch ( $id ) {
                case '=':
                case '==':
                    // translators: 1: Condition label, 2: Expected value.
                    $operator_messages[ $id ] = __( '%1$s must be %2$s', 'floating-awesome-button' );
                    break;

                case '!=':
                    // translators: 1: Condition label, 2: Value that must not match.
                    $operator_messages[ $id ] = __( '%1$s should not be %2$s', 'floating-awesome-button' );
                    break;

                case '>':
                    // translators: 1: Condition label, 2: Minimum value (exclusive).
                    $operator_messages[ $id ] = __( '%1$s must be more than %2$s', 'floating-awesome-button' );
                    break;

                case '<':
                    // translators: 1: Condition label, 2: Maximum value (exclusive).
                    $operator_messages[ $id ] = __( '%1$s must be under %2$s', 'floating-awesome-button' );
                    break;

                case '>=':
                    // translators: 1: Condition label, 2: Minimum value (inclusive).
                    $operator_messages[ $id ] = __( '%1$s must be at least %2$s', 'floating-awesome-button' );
                    break;

                case '<=':
                    // translators: 1: Condition label, 2: Maximum value (inclusive).
                    $operator_messages[ $id ] = __( '%1$s must be %2$s or less', 'floating-awesome-button' );
                    break;
            }
        }

        // Fallback message if not found.
        $message = isset( $operator_messages[ $operator ] )
            ? $operator_messages[ $operator ]
            // translators: 1: Condition label, 2: Expected value.
            : __( '%1$s must match %2$s.', 'floating-awesome-button' );

        $value = $this->_format_condition_value( $label, $value );

        return sprintf( $message, $label, $value );
    }

    /**
     * Get a human-readable description for a single location rule, optionally including logic (AND/OR)
     * unless it's the last rule in a group.
     *
     * @param array $rule  The location rule array. Must include 'type', 'operator', and 'value'.
     * @param int   $index The current rule index in the group (default: 0).
     * @param int   $total The total number of rules in the group (default: 1).
     *
     * @return string|null The formatted rule description, or null on failure.
     */
    private function _get_location_rule_description( $rule, $index = 0, $total = 1 ) {
        if ( ! isset( $rule['type'], $rule['operator'], $rule['value'] ) ) {
            return null;
        }

        $location_types = $this->_normalize_fab_location_types(
            array_merge(
                apply_filters( 'fab_location_types', array() ),
                isset( ( $m = apply_filters( 'fab_metabox_location_localize', array() ) )['types'] ) && is_array( $m['types'] ) ? $m['types'] : array() // phpcs:disable Squiz.PHP.DisallowMultipleAssignments.Found
            )
        );

        $rule_type = $rule['type'];
        $label     = isset( $location_types[ $rule_type ]['text'] )
            ? $location_types[ $rule_type ]['text']
            : ucfirst( str_replace( '_', ' ', ltrim( $rule_type, '_' ) ) );

        $value = $rule['value'];

        if ( is_array( $value ) ) {
            $value = array_values( $value );
            if ( isset( $value[0], $value[1] ) ) {
                $label = ucfirst( str_replace( '_', ' ', ltrim( $value[0], '_' ) ) );
                $value = $value[1];
            } else {
                $value = wp_json_encode( $value );
            }
        }

        $value = ucfirst( str_replace( '_', ' ', ltrim( $value, '_' ) ) );

        $logic_text = '';
        if ( $index < $total - 1 && isset( $rule['logic'][0] ) && in_array( strtoupper( $rule['logic'][0] ), array( 'AND', 'OR' ), true ) ) {
            $logic_text = ' <strong>' . strtoupper( $rule['logic'][0] ) . '</strong>';
        }

        return $this->_build_condition_description( $label, $rule['operator'], $value ) . $logic_text;
    }

    /**
     * Generate a human-readable description of location rules.
     *
     * @param array  $locations Location rules array.
     * @param string $message   Optional custom message to display before the rule list.
     * @return string HTML content describing the rules.
     */
    public function generate_location_rules_description( $locations, $message = '' ) {
        if ( empty( $locations ) || ! is_array( $locations ) ) {
            return '';
        }

        if ( empty( $message ) ) {
            $message = __( 'This feature is currently unavailable because the following conditions are not met', 'floating-awesome-button' );
        }

        $content  = '<div class="fab-location-rules-info space-y-6">';
        $content .= '<p class="font-semibold text-gray-800">' . esc_html( $message ) . '</p>';

        $total_groups     = count( $locations );
        $prev_group_logic = '';

        foreach ( $locations as $group_index => $group ) {
            if ( empty( $group['rules'] ) || ! is_array( $group['rules'] ) ) {
                continue;
            }

            if ( $total_groups > 1 ) {
                if ( 0 === $group_index ) {
                    $prev_group_logic = '';
                }
                $content .= '<p class="text-md mt-3 mb-1">' . $prev_group_logic . ' Condition ' . ( $group_index + 1 ) . '</p>';
            }

            $prev_group_logic = '<strong>' . $group['logic'] . '</strong>';

            $content .= '<div class="flex flex-col gap-y-2">';

            $total_rules = count( $group['rules'] );

            foreach ( $group['rules'] as $index => $rule ) {
                $description = $this->_get_location_rule_description( $rule, $index, $total_rules );

                if ( $description ) {
                    $content .= '<div class="px-4 py-2 border border-gray-300 shadow-md rounded-md bg-white text-sm text-gray-700 flex justify-between">';
                    $content .= $description;
                    $content .= '</div>';
                }
            }

            $content .= '</div>';
        }

        $content .= '</div>';

        return $content;
    }
}
