<?php

namespace BWDK\Woo\Order;

use BWDK\Support\Constant;
use WC_Order;

class ReferenceCodeHelper
{
    /**
     * Extract Digikala reference code from order meta.
     */
    public static function extractFromOrder(?WC_Order $order): string
    {
        if (!$order instanceof WC_Order) {
            return '';
        }

        $raw = $order->get_meta(Constant::META_BWDK_JSON_CB);
        $data = self::normaliseMetaValue($raw);

        if (!is_array($data)) {
            return '';
        }

        $code = self::searchArrayForKey($data, ['reference_code', 'referenceCode']);
        return is_string($code) ? trim($code) : '';
    }

    /**
     * @param mixed $value
     * @return mixed
     */
    protected static function normaliseMetaValue($value)
    {
        if ($value instanceof \stdClass) {
            $value = (array) $value;
        }

        if (is_string($value)) {
            $trimmed = trim($value);
            if ($trimmed === '') {
                return $value;
            }

            $json = json_decode($trimmed, true);
            if (json_last_error() === JSON_ERROR_NONE) {
                return $json;
            }

            $maybe = maybe_unserialize($trimmed);
            if ($maybe !== $value) {
                return $maybe;
            }
        }

        return $value;
    }

    /**
     * @param array<string,mixed> $data
     * @param array<int,string> $keys
     * @return mixed|null
     */
    protected static function searchArrayForKey(array $data, array $keys)
    {
        foreach ($data as $key => $value) {
            if (in_array($key, $keys, true) && !is_array($value) && !is_object($value)) {
                return $value;
            }

            if (is_array($value)) {
                $found = self::searchArrayForKey($value, $keys);
                if ($found !== null) {
                    return $found;
                }
            } elseif ($value instanceof \stdClass) {
                $found = self::searchArrayForKey((array) $value, $keys);
                if ($found !== null) {
                    return $found;
                }
            }
        }

        return null;
    }
}

