<?php

namespace KupShop\ContentBundle\Util;

use KupShop\ContentBundle\View\Exception\ValidationException;
use KupShop\KupShopBundle\Context\DomainContext;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\RecaptchaBundle\Util\RecaptchaGCloudUtil;
use ReCaptcha\ReCaptcha;
use ReCaptcha\RequestMethod\Post;

class Captcha
{
    /**
     * @param null $data
     * @param null $type One of null, 'shared', 'invisible', 'default'
     *
     * @throws ValidationException
     */
    public static function checkCaptcha($data = null, $type = null)
    {
        if (isFunctionalTests()) {
            return true;
        }

        if ($captcha = getVal('captcha', $data)) {
            if ($captcha != generateCaptcha(getVal('captcha_id', $data))) {
                throw new ValidationException(translate('errorCaptcha', 'form'));
            }
        } elseif ($captcha = getVal('g-recaptcha-response', $data)) {
            if (findModule(\Modules::RECAPTCHA, \Modules::SUB_GCLOUD)) {
                $util = ServiceContainer::getService(RecaptchaGCloudUtil::class);
                if (!$util->validate(token: $captcha, type: $type ?: getVal('recaptcha', $data))) {
                    throw new ValidationException(translate('errorCaptcha', 'form'));
                }
            } else {
                $key = self::getCaptchaType($type ?: getVal('recaptcha', $data));
                $recaptcha = new ReCaptcha(findModule('recaptcha', $key));
                $resp = $recaptcha->verify($captcha, $_SERVER['REMOTE_ADDR']);
                if (!$resp->isSuccess()) {
                    throw new ValidationException(translate('errorCaptcha', 'form'));
                }
                if ($type == 'shared' && isProduction()) {
                    $domainContext = ServiceContainer::getService(DomainContext::class);
                    if (array_search($resp->getHostname(), $domainContext->getSupported()) === false) {
                        throw new ValidationException('Invalid CAPTCHA domain');
                    }
                }
            }
        } elseif ($captcha = getVal('wpj-captcha-response', $data)) {
            $requestMethod = new Post('https://challenges.cloudflare.com/turnstile/v0/siteverify');
            $recaptcha = new ReCaptcha(findModule('recaptcha', 'secret_cloudflare'), $requestMethod);

            $resp = $recaptcha->verify($captcha, $_SERVER['REMOTE_ADDR']);

            if (!$resp->isSuccess()) {
                throw new ValidationException(translate('errorCaptcha', 'form'));
            }

            if (isProduction()) {
                $domains = Contexts::get(DomainContext::class)->getSupported();
                if (!in_array($resp->getHostname(), $domains)) {
                    throw new ValidationException('Invalid CAPTCHA domain');
                }
            }
        } elseif ($captcha = getVal('wpj-captcha-invisible-response', $data)) {
            $requestMethod = new Post('https://challenges.cloudflare.com/turnstile/v0/siteverify');
            $recaptcha = new ReCaptcha(findModule('recaptcha', 'secret_cloudflare_invisible'), $requestMethod);

            $resp = $recaptcha->verify($captcha, $_SERVER['REMOTE_ADDR']);

            if (!$resp->isSuccess()) {
                throw new ValidationException(translate('errorCaptcha', 'form'));
            }

            if (isProduction()) {
                $domains = Contexts::get(DomainContext::class)->getSupported();
                if (!in_array($resp->getHostname(), $domains)) {
                    throw new ValidationException('Invalid CAPTCHA domain');
                }
            }
        } else {
            throw new ValidationException(translate('errorCaptcha', 'form'));
        }
    }

    protected static function getCaptchaType($type)
    {
        switch ($type) {
            case 'invisible':
                return 'secret_invisible';
            case 'shared':
                return 'secret_shared';

            default:
                return 'secret';
        }
    }
}
