<?php

namespace Tests\Tenant;

use App\Facades\Settings;
use Illuminate\Support\Facades\Http;
use Mtc\Crm\Models\Form;
use Mtc\Crm\Models\FormQuestion;
use Tests\TenantTestCase;

class VerifyRecaptchaTest extends TenantTestCase
{
    private function createFormWithEmail(): array
    {
        $form = Form::factory()->create(['initial_status_id' => 1]);
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);

        return [$form, $email];
    }

    private function setRecaptchaSecretKey(string $value = 'test-secret-key'): void
    {
        Settings::make([
            'tab' => 'Integration',
            'section' => 'reCAPTCHA',
            'group' => 'Settings',
            'name' => 'Secret Key',
            'config_key' => 'recaptcha-secret-key',
            'value' => $value,
            'type' => 'string',
        ]);
    }

    public function testRequestPassesWhenNoSecretKeyConfigured(): void
    {
        [$form, $email] = $this->createFormWithEmail();

        $response = $this->postJson(route('enquiries.store'), [
            'id' => $form->id,
            'questions' => [
                $email->id => 'test@example.com',
            ],
        ]);

        $response->assertStatus(200);
    }

    public function testRequestFails422WhenSecretKeySetButNoToken(): void
    {
        $this->setRecaptchaSecretKey();
        [$form, $email] = $this->createFormWithEmail();

        $response = $this->postJson(route('enquiries.store'), [
            'id' => $form->id,
            'questions' => [
                $email->id => 'test@example.com',
            ],
        ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors('recaptcha_token');
    }

    public function testRequestFails422WhenGoogleReturnsFailure(): void
    {
        $this->setRecaptchaSecretKey();

        Http::fake([
            'www.google.com/recaptcha/api/siteverify' => Http::response([
                'success' => false,
                'error-codes' => ['invalid-input-response'],
            ]),
        ]);

        [$form, $email] = $this->createFormWithEmail();

        $response = $this->postJson(route('enquiries.store'), [
            'id' => $form->id,
            'questions' => [
                $email->id => 'test@example.com',
            ],
            'recaptcha_token' => 'fake-token',
        ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors('recaptcha_token');
    }

    public function testRequestFails422WhenScoreBelowThreshold(): void
    {
        $this->setRecaptchaSecretKey();

        Http::fake([
            'www.google.com/recaptcha/api/siteverify' => Http::response([
                'success' => true,
                'score' => 0.2,
                'action' => 'enquiry_submit',
            ]),
        ]);

        [$form, $email] = $this->createFormWithEmail();

        $response = $this->postJson(route('enquiries.store'), [
            'id' => $form->id,
            'questions' => [
                $email->id => 'test@example.com',
            ],
            'recaptcha_token' => 'low-score-token',
        ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors('recaptcha_token');
    }

    public function testRequestPassesWhenTokenIsValidAndScoreMeetsThreshold(): void
    {
        $this->setRecaptchaSecretKey();

        Http::fake([
            'www.google.com/recaptcha/api/siteverify' => Http::response([
                'success' => true,
                'score' => 0.9,
                'action' => 'enquiry_submit',
            ]),
        ]);

        [$form, $email] = $this->createFormWithEmail();

        $response = $this->postJson(route('enquiries.store'), [
            'id' => $form->id,
            'questions' => [
                $email->id => 'test@example.com',
            ],
            'recaptcha_token' => 'valid-token',
        ]);

        $response->assertStatus(200);
    }
}
