<?php

namespace Tests\Tenant;

use App\Facades\Feature;
use App\Facades\Settings;
use Carbon\Carbon;
use Mtc\Crm\Models\Enquiry;
use Mtc\Crm\Models\Form;
use Mtc\Crm\Models\FormQuestion;
use Mtc\MercuryDataModels\ResourceView;
use Mtc\MercuryDataModels\Vehicle;
use Tests\TenantTestCase;

class EnquiryControllerTest extends TenantTestCase
{
    public function testSubmitEnquiry()
    {
        $form = Form::factory()->create(['initial_status_id' => 1]);
        $first_name = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'text',
            'name' => 'First Name',
            'validation' => 'required',
        ]);
        $last_name = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'text',
            'name' => 'Last Name',
            'validation' => 'required',
        ]);
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);
        $phone = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'text',
            'name' => 'Phone Number',
            'validation' => 'required',
        ]);

        $message = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'textarea',
            'name' => 'Message',
            'validation' => 'required',
        ]);

        $response = $this
            ->postJson(route('enquiries.store'), [
                'id' => $form->id,
                'questions' => [
                    $first_name->id => 'Peter',
                    $last_name->id => 'Parker',
                    $email->id => 'john@example.com',
                    $phone->id => '12331231232',
                    $message->id => 'Loprem ipsum dolor sit amet',

                ]
            ]);
        $response->assertStatus(200);

        $this->assertTrue(Enquiry::query()->where('form_id', $form->id)->exists());
    }

    public function testSubmitWithReasonEnquiry()
    {
        $form = Form::factory()->create(['initial_status_id' => 1]);
        $first_name = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'text',
            'name' => 'First Name',
            'validation' => 'required',
        ]);
        $last_name = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'text',
            'name' => 'Last Name',
            'validation' => 'required',
        ]);
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);
        $phone = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'text',
            'name' => 'Phone Number',
            'validation' => 'required',
        ]);
        $page = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'page_id',
            'name' => 'Page ID',
        ]);

        $message = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'textarea',
            'name' => 'Message',
            'validation' => 'required',
        ]);

        $response = $this
            ->postJson(route('enquiries.store'), [
                'id' => $form->id,
                'questions' => [
                    $page->id => 'abc',
                    $first_name->id => 'Peter',
                    $last_name->id => 'Parker',
                    $email->id => 'john@example.com',
                    $phone->id => '12331231232',
                    $message->id => 'Loprem ipsum dolor sit amet',

                ]
            ]);
        $response->assertStatus(200);

        $this->assertTrue(Enquiry::query()->where('form_id', $form->id)->exists());
    }

    public function testMissingFields()
    {
        $form = Form::factory()->create();
        $first_name = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'text',
            'name' => 'First Name',
            'validation' => 'required',
        ]);
        $last_name = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'text',
            'name' => 'Last Name',
            'validation' => 'required',
        ]);
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);
        $phone = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'text',
            'name' => 'Phone Number',
            'validation' => 'required',
        ]);

        $message = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'textarea',
            'name' => 'Message',
        ]);

        $response = $this
            ->postJson(route('enquiries.store'), [
                'id' => $form->id,
                'questions' => [
                    $first_name->id => 'Peter',
                ]
            ]);
        $response->assertStatus(422);
        $this->assertArrayHasKey('questions.' . $last_name->id, $response->json('errors'));
        $this->assertArrayHasKey('questions.' . $email->id, $response->json('errors'));
        $this->assertArrayHasKey('questions.' . $phone->id, $response->json('errors'));
        $this->assertArrayNotHasKey('questions.' . $message->id, $response->json('errors'));
    }

    public function testEmailTypeValidation()
    {
        $form = Form::factory()->create();
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);
        $response = $this
            ->postJson(route('enquiries.store'), [
                'id' => $form->id,
                'questions' => [
                    $email->id => 'test-me',
                ]
            ]);
        $response->assertStatus(422);
        $this->assertArrayHasKey('questions.' . $email->id, $response->json('errors'));
    }

    public function testSuccessMessageIsReturned()
    {
        $form = Form::factory()->create(['success_message' => 'foo baz bar']);
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);
        $response = $this
            ->postJson(route('enquiries.store'), [
                'id' => $form->id,
                'questions' => [
                    $email->id => 'test@example.com',
                ]
            ]);
        $response->assertStatus(200);
        $this->assertArrayHasKey('status', $response->json());
        $this->assertArrayHasKey('message', $response->json());
        $this->assertArrayHasKey('enquiry_id', $response->json());
        $this->assertEquals('foo baz bar', $response->json('message'));
        $this->assertEquals('ok', $response->json('status'));
        $this->assertNotNull($response->json('enquiry_id'));
    }

    public function testRedirectUrlIsReturnedWhenSet()
    {
        $form = Form::factory()->create([
            'success_message' => 'thanks',
            'redirect_url' => 'https://example.com/thank-you',
        ]);
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);
        $response = $this
            ->postJson(route('enquiries.store'), [
                'id' => $form->id,
                'questions' => [
                    $email->id => 'test@example.com',
                ],
            ]);
        $response->assertStatus(200);
        $this->assertEquals('https://example.com/thank-you', $response->json('redirect_url'));
    }

    public function testRedirectUrlIsNullWhenNotSet()
    {
        $form = Form::factory()->create(['success_message' => 'thanks', 'redirect_url' => null]);
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);
        $response = $this
            ->postJson(route('enquiries.store'), [
                'id' => $form->id,
                'questions' => [
                    $email->id => 'test@example.com',
                ],
            ]);
        $response->assertStatus(200);
        $this->assertNull($response->json('redirect_url'));
    }

    public function testVehicleStatsReturnedWhenFeatureAndSettingEnabled()
    {
        Feature::setEnabled(tenant(), ['enquiry-vehicle-stats']);
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Enquiries',
            'group' => 'Response',
            'name' => 'Show vehicle stats after enquiry submission',
            'config_key' => 'crm-enquiry-vehicle-stats-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Enquiries',
            'group' => 'Response',
            'name' => 'Days to count views',
            'config_key' => 'crm-enquiry-vehicle-stats-days',
            'type' => 'number',
            'value' => 7,
        ]);

        $vehicle = Vehicle::factory()->create(['is_published' => true]);

        ResourceView::create([
            'viewable_type' => 'vehicle',
            'viewable_id' => $vehicle->id,
            'date' => Carbon::now()->subDays(3),
            'hits' => 150,
        ]);

        Enquiry::factory()->create([
            'reason_type' => 'vehicle',
            'reason_id' => $vehicle->id,
        ]);

        $form = Form::factory()->create(['initial_status_id' => 1]);
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);
        $vehicleQuestion = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'vehicle_id',
            'name' => 'Vehicle',
        ]);

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

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'status',
            'message',
            'enquiry_vehicle_stats' => [
                'days',
                'views',
                'total_enquiries',
            ],
        ]);
        $this->assertEquals(7, $response->json('enquiry_vehicle_stats.days'));
        $this->assertEquals(150, $response->json('enquiry_vehicle_stats.views'));
        $this->assertEquals(2, $response->json('enquiry_vehicle_stats.total_enquiries'));
    }

    public function testVehicleStatsNotReturnedWhenFeatureDisabled()
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Enquiries',
            'group' => 'Response',
            'name' => 'Show vehicle stats after enquiry submission',
            'config_key' => 'crm-enquiry-vehicle-stats-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);

        $vehicle = Vehicle::factory()->create(['is_published' => true]);

        $form = Form::factory()->create(['initial_status_id' => 1]);
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);
        $vehicleQuestion = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'vehicle_id',
            'name' => 'Vehicle',
        ]);

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

        $response->assertStatus(200);
        $this->assertEmpty($response->json('enquiry_vehicle_stats'));
    }

    public function testVehicleStatsNotReturnedWhenSettingDisabled()
    {
        Feature::setEnabled(tenant(), ['enquiry-vehicle-stats']);
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Enquiries',
            'group' => 'Response',
            'name' => 'Show vehicle stats after enquiry submission',
            'config_key' => 'crm-enquiry-vehicle-stats-enabled',
            'type' => 'boolean',
            'value' => false,
        ]);

        $vehicle = Vehicle::factory()->create(['is_published' => true]);

        $form = Form::factory()->create(['initial_status_id' => 1]);
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);
        $vehicleQuestion = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'vehicle_id',
            'name' => 'Vehicle',
        ]);

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

        $response->assertStatus(200);
        $this->assertEmpty($response->json('enquiry_vehicle_stats'));
    }

    public function testVehicleStatsNotReturnedForNonVehicleEnquiry()
    {
        Feature::setEnabled(tenant(), ['enquiry-vehicle-stats']);
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Enquiries',
            'group' => 'Response',
            'name' => 'Show vehicle stats after enquiry submission',
            'config_key' => 'crm-enquiry-vehicle-stats-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);

        $form = Form::factory()->create(['initial_status_id' => 1]);
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);

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

        $response->assertStatus(200);
        $this->assertEmpty($response->json('enquiry_vehicle_stats'));
    }

    public function testVehicleStatsViewsNullWhenBelowThreshold()
    {
        Feature::setEnabled(tenant(), ['enquiry-vehicle-stats']);
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Enquiries',
            'group' => 'Response',
            'name' => 'Show vehicle stats after enquiry submission',
            'config_key' => 'crm-enquiry-vehicle-stats-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Enquiries',
            'group' => 'Response',
            'name' => 'Minimum views threshold',
            'config_key' => 'crm-enquiry-vehicle-stats-views-threshold',
            'type' => 'number',
            'value' => 100,
        ]);
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Enquiries',
            'group' => 'Response',
            'name' => 'Days to count views',
            'config_key' => 'crm-enquiry-vehicle-stats-days',
            'type' => 'number',
            'value' => 7,
        ]);

        $vehicle = Vehicle::factory()->create(['is_published' => true]);

        ResourceView::create([
            'viewable_type' => 'vehicle',
            'viewable_id' => $vehicle->id,
            'date' => Carbon::now()->subDays(3),
            'hits' => 50,
        ]);

        $form = Form::factory()->create(['initial_status_id' => 1]);
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);
        $vehicleQuestion = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'vehicle_id',
            'name' => 'Vehicle',
        ]);

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

        $response->assertStatus(200);
        $this->assertNotEmpty($response->json('enquiry_vehicle_stats'));
        $this->assertEquals(7, $response->json('enquiry_vehicle_stats.days'));
        $this->assertNull($response->json('enquiry_vehicle_stats.views'));
        $this->assertEquals(1, $response->json('enquiry_vehicle_stats.total_enquiries'));
    }

    public function testVehicleStatsUsesConfiguredDaysSetting()
    {
        Feature::setEnabled(tenant(), ['enquiry-vehicle-stats']);
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Enquiries',
            'group' => 'Response',
            'name' => 'Show vehicle stats after enquiry submission',
            'config_key' => 'crm-enquiry-vehicle-stats-enabled',
            'type' => 'boolean',
            'value' => true,
        ]);
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Enquiries',
            'group' => 'Response',
            'name' => 'Days to count views',
            'config_key' => 'crm-enquiry-vehicle-stats-days',
            'type' => 'number',
            'value' => 14,
        ]);

        $vehicle = Vehicle::factory()->create(['is_published' => true]);

        ResourceView::create([
            'viewable_type' => 'vehicle',
            'viewable_id' => $vehicle->id,
            'date' => Carbon::now()->subDays(10),
            'hits' => 100,
        ]);

        $form = Form::factory()->create(['initial_status_id' => 1]);
        $email = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'email',
            'name' => 'Email',
            'validation' => 'required|email',
        ]);
        $vehicleQuestion = FormQuestion::factory()->create([
            'form_id' => $form->id,
            'type' => 'vehicle_id',
            'name' => 'Vehicle',
        ]);

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

        $response->assertStatus(200);
        $this->assertEquals(14, $response->json('enquiry_vehicle_stats.days'));
        $this->assertEquals(100, $response->json('enquiry_vehicle_stats.views'));
    }
}
