<?php

/**
 * Hyvä Themes - https://hyva.io
 * Copyright © Hyvä Themes 2020-present. All rights reserved.
 * This product is licensed per Magento install
 * See https://hyva.io/license
 */

use Hyva\GraphqlViewModel\ViewModel\GraphqlViewModel;
use Hyva\Theme\Model\ViewModelRegistry;
use Hyva\Theme\ViewModel\HeroiconsOutline;
use Hyva\Theme\ViewModel\HeroiconsSolid;
use Hyva\Theme\ViewModel\SvgIcons;
use Hyva\Theme\ViewModel\Store;
use Magento\Framework\Escaper;
use Magento\Review\Block\Form;
use Hyva\Theme\ViewModel\ReCaptcha;

//phpcs:disable Generic.Files.LineLength

/** @var Escaper $escaper */
/** @var Form $block */
/** @var ViewModelRegistry $viewModels */

/** @var HeroiconsOutline $heroicons */
$heroicons = $viewModels->require(HeroiconsOutline::class);

/** @var HeroiconsSolid $heroiconsSolid */
$heroiconsSolid = $viewModels->require(HeroiconsSolid::class);

/** @var SvgIcons $hyvaicons */
$hyvaicons = $viewModels->require(SvgIcons::class);

/** @var Store $viewModelStore */
$viewModelStore = $viewModels->require(Store::class);

$formId = 'review_form';

/** @var GraphqlViewModel $gqlViewModel */
$gqlViewModel = $viewModels->require(GraphqlViewModel::class);

// Do not replace this with $viewModels->require(ReCaptcha::class); that might break the dependency
// on Magento_ReCaptchaReview module
/** @var ReCaptcha $recaptcha */
$recaptcha = $block->getData('viewModelRecaptcha');

$gqlCreateProductReviewMutation = '
mutation createProductReviewMutation(
    $sku: String!,
    $nick: String!,
    $summary: String!,
    $review: String!,
    $ratings: [ProductReviewRatingInput]!
) {
    createProductReview(
        input: {
            sku: $sku,
            nickname: $nick,
            summary: $summary,
            text: $review,
            ratings: $ratings
        }
    ) {
        review {
            nickname
        }
    }
}
';

?>
<div class="mx-auto py-6 items-center" id="review-form" tabindex="-1">
    <div class="card w-full px-6 py-3">
        <div class="text-xl my-3">
            <?= $escaper->escapeHtml(__('Write Your Own Review')) ?>
        </div>
        <?php if ($block->getAllowWriteReviewFlag()): ?>
            <form class="review-form"
                  id="<?= $escaper->escapeHtmlAttr($formId) ?>"
                  @submit.prevent="submitForm()"
                  action=""
                  x-data="initReviewForm()"
                  x-defer="intersect"
            >
                <?= $block->getChildHtml('form_fields_before') ?>
                <?= $recaptcha ? $recaptcha->getInputHtml(ReCaptcha::RECAPTCHA_FORM_ID_PRODUCT_REVIEW) : '' ?>
                <fieldset>
                    <legend class="text-xs">
                        <span>
                            <?= $escaper->escapeHtml(__("You're reviewing:")) ?>
                        </span>
                        <span class="font-semibold">
                            <?= $escaper->escapeHtml($block->getProductInfo()->getName()) ?>
                        </span>
                    </legend>
                    <?php if ($block->getRatings() && $block->getRatings()->getSize()): ?>
                        <fieldset name="rating-group">
                            <div class="flex flex-col mt-4 mb-3">
                                <div class="text-md <?php if ($block->getRatings()->getSize() <= 1): ?>hidden<?php endif ?>">
                                    <?= $escaper->escapeHtml(__('Your Rating')) ?>:
                                </div>
                                <div class="mt-4">
                                    <div id="product-review-table">
                                        <?php foreach ($block->getRatings() as $rating): ?>
                                            <div class="table-row">
                                                <label
                                                    class="table-cell pr-6 align-middle text-left"
                                                    id="<?= $escaper->escapeHtmlAttr($rating->getRatingCode()) ?>_rating_label"
                                                >
                                                    <span>
                                                        <?php if ($block->getRatings()->getSize() <= 1): ?>
                                                            <?= $escaper->escapeHtml(__('Your Rating')) ?>:
                                                        <?php else: ?>
                                                            <?= $escaper->escapeHtml($rating->getRatingCode()) ?>
                                                        <?php endif ?>
                                                    </span>
                                                </label>
                                                <div
                                                    class="flex flex-row grow-0 focus-within:ring-4 ring-primary ring-opacity-50"
                                                    x-data="{ clickedRatingId: 0 }"
                                                >
                                                    <?php $options = $rating->getOptions(); ?>
                                                    <?php $iterator = 1;
                                                    foreach ($options as $option): ?>
                                                        <div
                                                            class="relative"
                                                            @click="clickedRatingId = <?= (int)$iterator ?> || 0"
                                                        >
                                                            <label
                                                                class="rating-<?= (int)$iterator ?> m-0 cursor-pointer text-gray-400"
                                                                for="<?= $escaper->escapeHtmlAttr($rating->getRatingCode() . '_' . $option->getValue()) ?>"
                                                                id="<?= $escaper->escapeHtmlAttr($rating->getRatingCode() . '_' . $option->getValue()) ?>_label"
                                                            >
                                                                <span :class="<?= (int)$iterator ?> <= clickedRatingId
                                                                    ? 'text-yellow-400'
                                                                    : 'text-gray-400'"
                                                                >
                                                                    <?= $heroiconsSolid->starHtml('', 32, 32, ["aria-hidden" => "true"]); ?>
                                                                </span>
                                                                <input
                                                                    class="absolute opacity-0 bottom-0 left-0 cursor-pointer"
                                                                    type="radio"
                                                                    <?php if ($iterator === 1): ?>required<?php endif; ?>
                                                                    name="ratings[<?= $escaper->escapeHtmlAttr($rating->getId()) ?>]"
                                                                    id="<?= $escaper->escapeHtmlAttr($rating->getRatingCode() . '_' . $option->getValue()) ?>"
                                                                    value="<?= $escaper->escapeHtmlAttr($option->getId()) ?>"
                                                                    <?php if ($iterator === 1): ?>
                                                                    aria-label="<?= $escaper->escapeHtmlAttr(__('1 star')) ?>"
                                                                    <?php else: ?>
                                                                    aria-label="<?= $escaper->escapeHtmlAttr(__('%1 stars', $iterator)) ?>"
                                                                    <?php endif; ?>
                                                                />
                                                            </label>

                                                        </div>
                                                        <?php $iterator++; ?>
                                                    <?php endforeach; ?>
                                                </div>
                                            </div>
                                        <?php endforeach; ?>
                                    </div>
                                    <input type="hidden" name="validate_rating" value=""/>
                                </div>
                            </div>
                        </fieldset>
                    <?php endif ?>
                    <div>
                        <div>
                            <label for="nickname_field" class="sr-only">
                                <span><?= $escaper->escapeHtml(__('Name')) ?></span>
                            </label>
                            <div>
                                <input class="form-input mt-3 block w-full"
                                       required
                                       placeholder="<?= $escaper->escapeHtmlAttr(__('Name') . '*') ?>" type="text"
                                       name="nickname" id="nickname_field"
                                       autocomplete="nickname"/>
                            </div>
                        </div>
                        <div>
                            <label for="summary_field" class="sr-only">
                                <span><?= $escaper->escapeHtml(__('Title')) ?></span>
                            </label>
                            <div>
                                <input class="form-input mt-3 block w-full"
                                       required
                                       placeholder="<?= $escaper->escapeHtmlAttr(__('Title') . '*') ?>" type="text"
                                       name="title"
                                       id="summary_field"
                                       autocomplete="off"/>
                            </div>
                        </div>
                        <div>
                            <label for="review_field" class="sr-only">
                                <span><?= $escaper->escapeHtml(__('Review Details')) ?></span>
                            </label>
                            <div>
                            <textarea class="form-input mt-3 block w-full"
                                      required
                                      placeholder="<?= $escaper->escapeHtmlAttr(__('Review Details') . '*') ?>" name="detail"
                                      id="review_field" cols="5"
                                      rows="3" autocomplete="off"></textarea>
                            </div>
                        </div>
                    </div>
                </fieldset>
                <div class="my-3">
                    <div>
                        <button x-show="!displaySuccessMessage" type="submit"
                                class="btn btn-primary">
                            <span>
                                <?= $escaper->escapeHtml(__('Submit Review')) ?>
                            </span>
                        </button>
                        <div class="flex flex-row justify-start items-center w-full"
                             x-show="isLoading"
                             x-cloak>
                            <?= $hyvaicons->loaderHtml('text-primary', 57, 57); ?>
                            <div class="ml-4 text-primary">
                                <?= $escaper->escapeHtml(__('Loading...')) ?>
                            </div>
                        </div>
                        <p x-show="displaySuccessMessage"
                           x-cloak
                           class="text-green flex items-center">
                            <span class="inline-block w-8 h-8 mr-3">
                                <?= $heroicons->checkCircleHtml('', 24, 24, ['aria-hidden' => true]); ?>
                            </span>
                            <?= $escaper->escapeHtml(__('You submitted your review for moderation.')) ?>
                        </p>
                        <template x-if="displayErrorMessage">
                            <p class="text-red flex items-center">
                                <span class="inline-block w-8 h-8 mr-3">
                                    <?= $heroicons->exclamationCircleHtml('', 24, 24, ['aria-hidden' => true]); ?>
                                </span>
                                <template x-for="errorMessage in errorMessages">
                                    <span x-html="errorMessage"></span>
                                </template>
                            </p>
                        </template>
                    </div>
                    <?= $block->getChildHtml('form_additional_after') ?>
                    <?= $recaptcha ? $recaptcha->getLegalNoticeHtml(ReCaptcha::RECAPTCHA_FORM_ID_PRODUCT_REVIEW) : '' ?>
                </div>
            </form>

            <script>
                function initReviewForm() {

                    return {
                        isLoading: false,
                        displayNickname: false,
                        displaySuccessMessage: false,
                        displayErrorMessage: false,
                        errorMessages: [],
                        errors: 0,
                        hasCaptchaToken: 0,
                        nickname: null,
                        summary: null,
                        ratings: [],
                        review: null,
                        setErrorMessages: function (messages) {
                            this.errorMessages = [messages]
                            this.displayErrorMessage = this.errorMessages.length
                        },
                        submitForm: function () {
                            // Do not remove $form. The variable is used in the recaptcha child template.
                            const $form = document.querySelector('#<?= $escaper->escapeJs($formId) ?>');
                            this.validate();

                            <?= $recaptcha ? $recaptcha->getValidationJsHtml(ReCaptcha::RECAPTCHA_FORM_ID_PRODUCT_REVIEW) : '' ?>

                            if (this.errors === 0) {
                                this.placeReview();
                            }
                        },
                        validate: function () {
                            this.nickname = document.getElementById('nickname_field').value;
                            this.summary = document.getElementById('summary_field').value;
                            this.review = document.getElementById('review_field').value;

                            let ratingValue;
                            <?php foreach ($block->getRatings() as $rating): ?>
                            try {
                                ratingValue =
                                    document
                                        .querySelector('input[name="ratings[<?= (int)$rating->getId() ?>]"]:checked')
                                        .value;
                                this.ratings[<?= (int) $rating->getId() ?>] = btoa(ratingValue);
                            } catch (e) {
                                console.log(e);
                            }
                            <?php endforeach; ?>

                            if (!(this.nickname &&
                                this.summary &&
                                this.review &&
                                Object.keys(this.ratings).length === <?= count($block->getRatings()) ?>
                            )) {
                                this.setErrorMessages(
                                    ['<?= $escaper->escapeJs(__('Please verify you\'ve entered all required information')) ?>']
                                );
                                this.displayErrorMessage = true;
                                this.errors = 1;
                                this.hasCaptchaToken = 0;
                            }
                        },
                        placeReview: function () {
                            this.isLoading = true;
                            this.displayErrorMessage = false;

                            const query = `<?= /* @noEscape */ $gqlViewModel->query('create_product_review_mutation', $gqlCreateProductReviewMutation) ?>`;
                            const variables = {
                                sku: '<?= $escaper->escapeJs($block->getProductInfo()->getSku()) ?>',
                                nick: this.nickname,
                                summary: this.summary,
                                review: this.review,
                                ratings: Object.keys(this.ratings).map(key => {
                                    return {id: btoa(key), value_id: this.ratings[key]}
                                })
                            };

                            const form = document.querySelector('#<?= $escaper->escapeJs($formId) ?>');

                            const fieldName = '<?= $recaptcha
                                ? $escaper->escapeJs($recaptcha->getResultTokenFieldName($formId))
                                : '' ?>';
                            const recaptchaHeader = fieldName && form && form.elements[fieldName]
                                ? {'X-ReCaptcha': form.elements[fieldName].value}
                                : {};

                            fetch(`${BASE_URL}graphql`, {
                                method: 'POST',
                                headers: Object.assign({
                                    'Content-Type': 'application/json;charset=utf-8',
                                    'Store': '<?= $escaper->escapeJs($viewModelStore->getStoreCode()) ?>'
                                }, recaptchaHeader),
                                credentials: 'include',
                                body: JSON.stringify({query: query, variables: variables})
                            })
                                .then(response => response.json())
                                .then(data => {
                                        this.isLoading = false;
                                        if (data.errors) {
                                            this.setErrorMessages(['<?= $escaper->escapeJs(__('Submitting your review failed, please try again.')) ?>']);
                                            this.displayErrorMessage = true;
                                        } else {
                                            this.displaySuccessMessage = true;
                                        }
                                    }
                                );
                        }
                    }
                }
            </script>
        <?php else: ?>
            <div
                id="review-form"
                tabindex="-1"
            >
                <div class="pb-6">
                    <?= $escaper->escapeHtml(
                        __(
                            'Only registered users can write reviews. Please <a href="%1" class="underline">Sign in</a> or <a href="%2" class="underline">create an account</a>',
                            $block->getLoginLink(),
                            $block->getRegisterUrl()
                        ),
                        ['a']
                    ) ?>
                </div>
            </div>
        <?php endif ?>
    </div>
</div>
