<?php
if (!defined('ABSPATH')) exit;

class FORMFORGE_Value_Formatter {
    public static function is_internal_field_key($key) {
        $key = (string) $key;
        return $key !== '' && $key[0] === '_';
    }

    public static function payment_summary_fields($data, $payment_status = '') {
        if (!is_array($data)) return [];

        $payment_bag = [];
        foreach (['_payment', '__payment'] as $key) {
            if (isset($data[$key]) && is_array($data[$key])) {
                $payment_bag = $data[$key];
                break;
            }
        }

        $field_row = null;
        foreach ($data as $key => $field) {
            if (self::is_internal_field_key($key) || !is_array($field)) continue;
            if (($field['type'] ?? '') === 'payment') {
                $field_row = $field;
                break;
            }
        }

        $status = (string) ($payment_bag['status'] ?? '');
        if ($status === '' && $payment_status !== '') $status = (string) $payment_status;

        $amount = isset($payment_bag['amount']) ? (int) $payment_bag['amount'] : 0;
        if ($amount <= 0 && $field_row && isset($field_row['amount'])) {
            $amount = (int) $field_row['amount'];
        }

        $currency = strtolower((string) ($payment_bag['currency'] ?? ''));
        if ($currency === '' && $field_row && !empty($field_row['currency'])) {
            $currency = strtolower((string) $field_row['currency']);
        }

        $updated_at = (string) ($payment_bag['updated_at'] ?? '');

        $fields = [];
        if ($status !== '') {
            $fields['payment_status'] = [
                'label' => __('Payment status', 'formforge'),
                'value' => $status,
                'type'  => 'text',
            ];
        }
        if ($amount > 0 && $currency !== '') {
            $fields['payment_amount'] = [
                'label' => __('Payment amount', 'formforge'),
                'value' => strtoupper($currency) . ' ' . number_format($amount / 100, 2),
                'type'  => 'text',
            ];
        }
        if ($updated_at !== '') {
            $fields['payment_date'] = [
                'label' => __('Payment date', 'formforge'),
                'value' => self::format_datetime($updated_at, $updated_at),
                'type'  => 'text',
            ];
        }
        $payment_id = (string) ($payment_bag['payment_id'] ?? $payment_bag['payment_intent'] ?? '');
        if ($payment_id === '' && $field_row && !empty($field_row['value'])) {
            $payment_id = (string) $field_row['value'];
        }
        if ($payment_id !== '') {
            $fields['payment_id'] = [
                'label' => __('Payment intent', 'formforge'),
                'value' => $payment_id,
                'type'  => 'text',
            ];
        }

        return $fields;
    }

    public static function submission_display_fields($data, $args = []) {
        if (!is_array($data)) return [];

        $include_empty = !empty($args['include_empty']);
        $empty_value = array_key_exists('empty_value', $args) ? (string) $args['empty_value'] : '';
        $payment_status = isset($args['payment_status']) ? (string) $args['payment_status'] : '';

        $fields = [];
        foreach ($data as $key => $field) {
            if (self::is_internal_field_key($key) || !is_array($field)) continue;
            if (($field['type'] ?? '') === 'payment') continue;
            $value = self::field_text($field, $empty_value);
            if (!$include_empty && $value === '') continue;
            $label = trim((string) ($field['label'] ?? ''));
            $fields[(string) $key] = [
                'label' => $label !== '' ? $label : (string) $key,
                'value' => $value,
                'type'  => $field['type'] ?? 'text',
            ];
        }

        foreach (self::payment_summary_fields($data, $payment_status) as $key => $field) {
            if (!$include_empty && self::text($field['value'] ?? '', '') === '') continue;
            $fields[$key] = $field;
        }

        return $fields;
    }

    public static function field_text($field, $empty = '') {
        if (!is_array($field)) {
            return self::text($field, $empty);
        }

        $type = (string) ($field['type'] ?? '');
        $value = $field['value'] ?? '';

        if ($type === 'password') {
            return self::text($value, '') === '' ? $empty : '••••••••';
        }

        if ($type === 'checkbox') {
            if (is_scalar($value)) {
                $raw = strtolower(trim((string) $value));
                if (in_array($raw, ['1', 'yes', 'true', 'on', 'checked'], true)) {
                    return __('Yes', 'formforge');
                }
                if (in_array($raw, ['0', 'no', 'false', 'off'], true)) {
                    return $empty;
                }
            }
        }

        if (in_array($type, ['calendar_picker', 'date', 'time'], true)) {
            return self::format_datetime($value, self::text($value, $empty));
        }

        if ($type === 'repeater') {
            return self::repeater_text($value, $field['sub_fields'] ?? [], $empty);
        }

        return self::text($value, $empty);
    }

    public static function text($value, $empty = '') {
        if ($value === null || $value === false) {
            return $empty;
        }

        if (is_bool($value)) {
            return $value ? __('Yes', 'formforge') : $empty;
        }

        if (is_scalar($value)) {
            $text = trim((string) $value);
            $map = self::decode_map_address($text);
            if (is_array($map)) {
                return self::map_address_text($map, $empty);
            }
            return $text === '' ? $empty : $text;
        }

        if (!is_array($value)) {
            return $empty;
        }

        if (isset($value['type']) && is_string($value['type']) && array_key_exists('value', $value)) {
            return self::field_text($value, $empty);
        }

        if (self::looks_like_map_address($value)) {
            return self::map_address_text($value, $empty);
        }

        if (isset($value['file']) && is_array($value['file'])) {
            return self::text($value['file'], $empty);
        }

        if (isset($value['name']) && is_scalar($value['name'])) {
            return self::text($value['name'], $empty);
        }

        if (array_key_exists('value', $value) && count($value) <= 3) {
            return self::text($value['value'], $empty);
        }

        if (self::is_list($value)) {
            $parts = [];
            foreach ($value as $item) {
                $part = self::text($item, '');
                if ($part !== '') $parts[] = $part;
            }
            return empty($parts) ? $empty : implode(', ', $parts);
        }

        $lines = [];
        foreach ($value as $key => $item) {
            $part = self::text($item, '');
            if ($part === '') continue;
            $lines[] = self::label_from_key((string) $key) . ': ' . $part;
        }

        return empty($lines) ? $empty : implode("\n", $lines);
    }

    public static function html($value, $empty = '') {
        $text = self::text($value, $empty);
        if ($text === '') return '';
        return nl2br(esc_html($text));
    }

    private static function is_list(array $value) {
        if (function_exists('array_is_list')) {
            return array_is_list($value);
        }
        $i = 0;
        foreach ($value as $key => $_) {
            if ($key !== $i++) return false;
        }
        return true;
    }

    private static function label_from_key($key) {
        $key = preg_replace('/[_-]+/', ' ', $key);
        $key = trim((string) $key);
        if ($key === '') return __('Value', 'formforge');
        return ucwords($key);
    }

    private static function decode_map_address($text) {
        if ($text === '' || $text[0] !== '{') {
            return null;
        }

        $decoded = json_decode($text, true);
        if (!is_array($decoded)) {
            $decoded = json_decode(wp_unslash($text), true);
        }

        return is_array($decoded) && self::looks_like_map_address($decoded)
            ? $decoded
            : null;
    }

    private static function looks_like_map_address(array $value) {
        $has_map_key = array_key_exists('address', $value)
            || array_key_exists('formatted', $value)
            || array_key_exists('lat', $value)
            || array_key_exists('lng', $value);
        if (!$has_map_key) {
            return false;
        }

        return array_key_exists('address', $value)
            || array_key_exists('formatted', $value)
            || (array_key_exists('lat', $value) && array_key_exists('lng', $value));
    }

    private static function map_address_text(array $value, $empty) {
        $address = self::clean_map_scalar($value['formatted'] ?? '');
        if ($address === '') {
            $address = self::clean_map_scalar($value['address'] ?? '');
        }

        $lat = self::clean_map_scalar($value['lat'] ?? '');
        $lng = self::clean_map_scalar($value['lng'] ?? '');

        $lines = [];
        if ($address !== '' && !self::map_address_is_coords_only($address, $lat, $lng)) {
            $lines[] = __('Address', 'formforge') . ': ' . $address;
        }
        if ($lat !== '' && $lng !== '') {
            $lines[] = __('Coordinates', 'formforge') . ': ' . $lat . ', ' . $lng;
        }

        return empty($lines) ? $empty : implode("\n", $lines);
    }

    private static function clean_map_scalar($value) {
        if (!is_scalar($value)) {
            return '';
        }
        $text = wp_unslash((string) $value);
        $text = trim($text);
        return preg_replace('/\s+/', ' ', $text);
    }

    private static function map_address_is_coords_only($address, $lat, $lng) {
        if ($address === '' || $lat === '' || $lng === '') return false;
        $normalize = function ($value) {
            $value = strtolower(trim((string) $value));
            $value = preg_replace('/\s+/', '', $value);
            return str_replace(['lat:', 'lng:', 'latitude:', 'longitude:'], '', $value);
        };
        $addr = $normalize($address);
        $coords = $normalize($lat . ',' . $lng);
        return $addr === $coords || $addr === $normalize($lat . ' ' . $lng);
    }

    private static function format_datetime($value, $fallback = '') {
        $raw = self::text($value, '');
        if ($raw === '') return $fallback;

        $ts = strtotime($raw);
        if (!$ts) return $fallback !== '' ? $fallback : $raw;

        $date_format = get_option('date_format', 'Y-m-d');
        $time_format = get_option('time_format', 'H:i');
        $has_time = preg_match('/[T\s]\d{1,2}:\d{2}/', $raw) === 1;
        $format = $has_time ? trim($date_format . ' ' . $time_format) : $date_format;

        return date_i18n($format, $ts);
    }

    private static function repeater_text($value, $sub_fields = [], $empty = '') {
        if (!is_array($value)) return $empty;

        $label_map = [];
        if (is_array($sub_fields)) {
            foreach ($sub_fields as $sf) {
                if (!is_array($sf) || empty($sf['id'])) continue;
                $label_map[(string) $sf['id']] = trim((string) ($sf['label'] ?? $sf['id']));
            }
        }

        $lines = [];
        foreach ($value as $row) {
            if (!is_array($row)) {
                $part = self::text($row, '');
                if ($part !== '') $lines[] = '- ' . $part;
                continue;
            }

            $parts = [];
            foreach ($row as $key => $item) {
                $part = self::text($item, '');
                if ($part === '') continue;
                if (count($row) === 1) {
                    $parts[] = $part;
                } else {
                    $label = $label_map[(string) $key] ?? self::label_from_key((string) $key);
                    $parts[] = $label . ': ' . $part;
                }
            }
            if ($parts) $lines[] = '- ' . implode('; ', $parts);
        }

        return $lines ? implode("\n", $lines) : $empty;
    }
}
