<?php

namespace RTMCustomMails\EmailSections;

use ReflectionMethod;
use RTMCustomMails\Util;
use RTMMailComposer\Model\EmailSection;
use WC_Order;
use WordpressModels\Traits\SingletonTrait;

class SectionValidation
{

    use SingletonTrait;

    public function __construct()
    {
        add_filter('wrce_email_allowed_variables/object_type=order', [$this, 'getAllowedContextVarsOrderType']);
    }

    /**
     * @param string $emailId
     * @param EmailSection[] $sections
     * @return array
     */
    public function validateEmailWithSections(string $emailId, array $sections): array
    {
        $email = Util::getEmailById($emailId);

        $allowedVariables = array_unique([
            ...apply_filters('wrce_email_allowed_variables/object_type=' . $email->getObjectType(), [
                'recipient_name'
            ]),
            ...apply_filters('wrce_email_allowed_variables/email_id=' . $email->id, [
                'recipient_name'
            ]),
            ...array_keys($email->getRenderContext())]);

        $diff = [];
        foreach ($sections as $section) {
            $sectionUsedTokens = self::sectionUsedTokens($section);
            $sectionUsedVariables = $sectionUsedTokens['variables'];
            $diff = array_diff($sectionUsedVariables, $allowedVariables);
        }

        return array_map(fn(string $invalidVariable) => [
            'property' => 'text',
            'message' => "Variable \"{$invalidVariable}\" is not allowed in this email, chose one of: \"" . join('", "', $allowedVariables) . '"'
        ], $diff);
    }


    public function sectionUsedTokens(EmailSection $section): array
    {
        $text = $section->getText();

        $matches = [];
        $variablesUsed = [];
        if (preg_match_all('/\{\{\s+([\w_]+)[^}(]+}}/', $text, $matches)) {
            $variablesUsed = $matches[1];
        }

        $functionsUsed = [];
        if (preg_match_all('/\{\{\s+([\w_]+)\([^}]+}}/', $text, $matches)) {
            $functionsUsed = $matches[1];
        }

        return ['variables' => $variablesUsed, 'functions' => $functionsUsed];
    }


    public function getAllowedContextVarsOrderType($vars = []): array
    {
        $order = new WC_Order();
        $order_getters = Util::getClassMethods($order, 'get_order_', []);
        $billing_getters = Util::getClassMethods($order, 'get_billing_', []);
        $formatted_getters = Util::getClassMethods($order, 'get_formatted_', []);
        $customer_getters = Util::getClassMethods($order, 'get_customer_', ['id', 'ip_address', 'user_agent']);

        $names = array_map(fn(ReflectionMethod $method) => substr($method->getName(), 4), [
            ...$order_getters,
            ...$billing_getters,
            ...$formatted_getters,
            ...$customer_getters,
        ]);

        return array_unique([
            ...$vars,
            ...$names,
            'customer',
            'order',
        ]);
    }
}
