<?php

namespace Tests\Feature;

use App\Facades\Settings;
use App\Http\Resources\LiveChatResource;
use App\Http\Resources\MakeListResource;
use App\Http\Resources\MenuResource;
use App\Http\Resources\OfferListResource;
use App\Http\Resources\PageListResource;
use App\Http\Resources\PhoneNumberDisplay;
use App\Http\Resources\SiteResource;
use App\Http\Resources\UiBrands;
use App\Http\Resources\UiResponsiveProductList;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Mtc\ContentManager\Models\ContentElementField;
use Mtc\Crm\Models\Form;
use Mtc\Crm\Models\FormQuestion;
use Mtc\Crm\Models\FormSection;
use Mtc\MercuryDataModels\ContentElement;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Franchise;
use Mtc\MercuryDataModels\GlobalContent;
use Mtc\MercuryDataModels\Menu;
use Mtc\MercuryDataModels\MenuEntry;
use Mtc\MercuryDataModels\OfferType;
use Mtc\MercuryDataModels\OfferView;
use Mtc\MercuryDataModels\Page;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleMake;
use Mtc\MercuryDataModels\VehicleModel;
use Mtc\MercuryDataModels\VehicleOffer;
use Tests\TestCase;

class ResourceTest extends TestCase
{
    use RefreshDatabase;
    use PhoneNumberDisplay;

    protected $tenancy = true;

    public function testPhoneNumberDisplay()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'app-phone-number-format',
            'value' => '3-3-4',
            'type' => 'string',
        ]);

        $this->assertEquals('012 322 4444', $this->displayNumber('0123224444'));
        Settings::update('app-phone-number-format', '4-3-3');
        $this->assertEquals('0123 224 444', $this->displayNumber('0123224444'));
        Settings::update('app-phone-number-format', null);
        $this->assertEquals('0123224444', $this->displayNumber('0123224444'));
    }

    public function testSiteResource()
    {
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'app-name',
            'value' => 'foo baz bar',
            'type' => 'string',
        ]);

        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'app-contact-phone_number',
            'value' => '01382000111',
            'type' => 'string',
        ]);


        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'app-contact-contact_email',
            'value' => 'foo@baz.bar',
            'type' => 'string',
        ]);

        $menu = Menu::factory()->create(['slug' => 'header-main']);
        MenuEntry::factory(10)->create(['menu_id' => $menu->id]);

        $resource = (new SiteResource([]))->toArray(request());

        $this->assertArrayHasKey('id', $resource);
        $this->assertArrayHasKey('name', $resource);
        $this->assertArrayHasKey('currency', $resource);
        $this->assertArrayHasKey('favicon', $resource);
        $this->assertArrayHasKey('apple-touch', $resource);
        $this->assertArrayHasKey('suspended', $resource);
        $this->assertArrayHasKey('branding', $resource);
        $this->assertArrayHasKey('header', $resource);
        $this->assertArrayHasKey('footer', $resource);
        $this->assertArrayHasKey('liveChat', $resource);
        $this->assertArrayHasKey('contact_phone_number', $resource);
        $this->assertArrayHasKey('franchiseMenu', $resource['header']);
        $this->assertEquals('foo baz bar', $resource['name']);
        $this->assertEquals('01382000111', $resource['contact_phone_number']);
        $this->assertEquals('foo@baz.bar', $resource['contact_email']);
    }

    public function testFooter()
    {
        $footer_text = 'Example Text';
        $footer_text_two = 'More Text';

        ContentElement::query()->create([
            'id' => 1,
            'title' => 'Footer',
            'slug' => null,
            'subtitle' => '',
            'icon' => null,
            'category' => 'simple',
            'ui_component' => null,
            'is_enabled' => 1,
            'drag_and_drop' => false,
            'data' => null,
        ]);

        ContentElementField::query()->create([
            'id' => 1,
            'element_id' => 1,
            'child_element_id' => null,
            'field_type' => 'text',
            'slug' => 'text-field',
            'name' => 'Text Field',
            'data' => [
                'nestable' => false,
                'nestedLimit' => null,
                'editable' => true,
                'repeatable' => false,
                'validation' => []
            ],
            'meta' => '[]',
            'order' => 0
        ]);

        GlobalContent::query()->create([
            'id' => 1,
            'name' => 'Footer',
            'slug' => 'footer',
            'type' => null,
            'ui_component' => null,
            'content' => [
                [
                    'id' => 1,
                    'slug' => 'text-field',
                    'content' => $footer_text
                ],
                [
                    'id' => 2,
                    'slug' => 'text-field-two',
                    'content' => $footer_text_two
                ]
            ],
            'element_id' => 1,
        ]);

        $this->assertCount(1, ContentElement::all());
        $this->assertCount(1, ContentElementField::all());
        $this->assertCount(1, GlobalContent::all());

        $resource = (new SiteResource([]))->toArray(request());

        $this->assertArrayHasKey('footer', $resource);
        $this->assertArrayHasKey('footer_data', $resource['footer']);
        $this->assertNotEmpty($resource['footer']['footer_data']);
        $this->assertCount(6, $resource['footer']['footer_data']);
        $this->assertContains($footer_text, $resource['footer']['footer_data']['value'][0]);
        $this->assertContains($footer_text_two, $resource['footer']['footer_data']['value'][1]);
    }

    public function testMenuResource()
    {
        $element = ContentElement::factory()->create();
        $menu = Menu::factory()->create([
            'slug' => 'header-main',
            'first_child_element_id' => $element->id,
        ]);
        MenuEntry::factory(10)->create([
            'menu_id' => $menu->id,
            'parent_id' => null,
            'is_enabled' => true,
        ]);

        MenuEntry::factory(4)->create([
            'menu_id' => $menu->id,
            'parent_id' => null,
            'is_enabled' => false,
        ]);

        $resource = (new MenuResource($menu))->toArray(request());
        $this->assertIsArray($resource);
        $this->assertCount(10, $resource);
        $this->assertArrayHasKey('name', $resource[0]);
        $this->assertArrayHasKey('url', $resource[0]);
        $this->assertArrayHasKey('content', $resource[0]);
        $this->assertArrayHasKey('children', $resource[0]);
    }

    public function testUiBrands()
    {
        $makes = VehicleMake::factory(10)->create();
        $resource = (new UiBrands((object)['content' => $makes->pluck('id')]))->toArray(request());
        $this->assertIsArray($resource);
        $this->assertCount(10, $resource);
        $this->assertArrayHasKey('name', $resource[0]);
        $this->assertArrayHasKey('image', $resource[0]);
        $this->assertArrayHasKey('url', $resource[0]);
    }

    public function testUiResponsiveProductList()
    {
        Vehicle::factory(5)->create(['is_published' => true, 'featured' => 1]);
        $resource = (new UiResponsiveProductList((object)['name' => 'foo baz bar']))->toArray(request());
        $this->assertEquals('foo baz bar', $resource['name']);
        $this->assertArrayHasKey('items', $resource);
        $this->assertCount(4, $resource['items']);
    }

    public function testOfferListResource()
    {
        $make = VehicleMake::factory()->create();
        $model = VehicleModel::factory()->create(['make_id' => $make->id]);
        $type = OfferType::factory()->create();

        $offers = VehicleOffer::factory(20)->create([
            'make_id' => $make->id,
            'model_id' => $model->id,
            'type_id' => $type->id,
        ]);

        $resource = (new OfferListResource($offers))->toArray(request());

        $this->assertCount(20, $resource);
        $this->assertArrayHasKey('slug', $resource[0]);
        $views = OfferView::query()->where('offer_id', $offers->first()->id)->first();
        $this->assertEquals(1, $views->filter_views);

        $paginated = VehicleOffer::query()
            ->with([
                'offerType',
                'make',
                'model',
                'primaryMediaUse'
            ])
            ->withListingRelationships()
            ->paginate(10);

        $resource2 = (new OfferListResource($paginated))->toArray(request());

        $this->assertArrayHasKey('data', $resource2);
        $this->assertEquals(20, $resource2['total']);

        $views = OfferView::query()->where('offer_id', $offers->first()->id)->first();
        $this->assertEquals(2, $views->filter_views);
    }

    public function testMakeListResource()
    {
        $makes = VehicleMake::factory(10)->create();

        $resource = (new MakeListResource($makes))->toArray(request());

        $this->assertCount(10, $resource);
        $this->assertArrayHasKey('name', $resource[0]);
        $this->assertArrayHasKey('image', $resource[0]);

        $paginated = VehicleMake::query()
            ->paginate(5);
        $resource2 = (new MakeListResource($paginated))->toArray(request());
        $this->assertArrayHasKey('data', $resource2);
        $this->assertEquals(10, $resource2['total']);
    }

    public function testLiveChatResource()
    {
        $resource = (new SiteResource([]))->toArray(request());
        $this->assertNull($resource['liveChat']);
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'chat-zendesk-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);
        Settings::make([
            'tab' => 'foo',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'dolor',
            'config_key' => 'chat-zendesk-key',
            'value' => 'foo baz bar',
            'type' => 'string',
        ]);

        $resource = (new SiteResource([]))->toArray(request());

        $this->assertInstanceOf(LiveChatResource::class, $resource['liveChat']);
        $data = $resource['liveChat']->toArray(request());
        $this->assertArrayHasKey('widget', $data);
        $this->assertArrayHasKey('data', $data);
        $this->assertArrayHasKey('key', $data['data']);
        $this->assertEquals('foo baz bar', $data['data']['key']);
    }

    public function testPageListResource()
    {
        $makes = Page::factory(10)->create([
            'status' => 'published',
            'published_at' => Carbon::now()
        ]);

        $resource = (new PageListResource($makes))->toArray(request());

        $this->assertCount(10, $resource);
        $this->assertArrayHasKey('url', $resource[0]);
        $this->assertArrayHasKey('title', $resource[0]);
        $this->assertArrayHasKey('thumbnail', $resource[0]);

        $paginated = Page::query()
            ->with(['primaryMediaUse.media', 'categories', 'tags'])
            ->paginate(5);
        $resource2 = (new PageListResource($paginated))->toArray(request());
        $this->assertArrayHasKey('data', $resource2);
        $this->assertEquals(10, $resource2['total']);
    }

    public function testSiteResourceNoFranchise()
    {
        $resource = (new SiteResource([]))->toArray(request());

        $this->assertArrayHasKey('franchises', $resource);
        $this->assertEmpty($resource['franchises']);
    }

    public function testSiteResourceFranchise()
    {
        Franchise::factory()->create();

        $resource = (new SiteResource([]))->toArray(request());

        $this->assertArrayHasKey('franchises', $resource);
        $this->assertCount(1, $resource['franchises']);
        $this->assertArrayHasKey('dealerships', $resource['franchises'][0]);
        $this->assertCount(0, $resource['franchises'][0]['dealerships']);
    }

    public function testSiteResourceFranchiseDealerships()
    {
        $franchise = Franchise::factory()->create();
        $dealership = Dealership::factory()->create([
            'franchise_id' => $franchise->id + 1,
            'contact_no' => '789',
        ]);
        Dealership::factory(2)->create([
            'franchise_id' => $franchise->id,
            'contact_no' => '12345',
        ]);

        DB::insert('INSERT INTO dealership_franchises (dealership_id, franchise_id) VALUES (?, ?)',
            [
                $dealership->id,
                $franchise->id,
            ]);

        $resource = (new SiteResource([]))->toArray(request());

        $this->assertArrayHasKey('franchises', $resource);
        $this->assertArrayHasKey('dealerships', $resource['franchises'][0]);
        $this->assertCount(3, $resource['franchises'][0]['dealerships']);
        $this->assertArrayHasKey('name', $resource['franchises'][0]['dealerships'][0]);
        $this->assertArrayHasKey('contact_no', $resource['franchises'][0]['dealerships'][0]);
        $this->assertArrayHasKey('email', $resource['franchises'][0]['dealerships'][0]);

        $contact_numbers = collect($resource['franchises'][0]['dealerships'])->pluck('contact_no');

        $this->assertContains('12345', $contact_numbers);
        $this->assertContains('789', $contact_numbers);
    }

    public function testSiteResourceNewsletterFormEmpty()
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Newsletter',
            'group' => 'General',
            'name' => 'Form ID',
            'config_key' => 'newsletters-form-id',
            'type' => 'int',
            'min_tier' => 'standard',
            'value' => null,
        ]);

        Form::factory()->create([
            'id' => 5,
            'name' => 'newsletter',
        ]);

        $resource = (new SiteResource([]))->toArray(request());

        $this->assertArrayHasKey('footer', $resource);
        $this->assertArrayHasKey('subscribe', $resource['footer']);
        $this->assertArrayHasKey('form', $resource['footer']['subscribe']);
        $this->assertNull($resource['footer']['subscribe']['form']);
    }

    public function testSiteResourceNewsletterForm()
    {
        Settings::make([
            'tab' => 'CRM',
            'section' => 'Newsletter',
            'group' => 'General',
            'name' => 'Form ID',
            'config_key' => 'newsletters-form-id',
            'type' => 'int',
            'min_tier' => 'standard',
            'value' => 5,
        ]);

        $form = Form::factory()->create([
            'id' => 5,
            'name' => 'newsletter',
        ]);

        $section = FormSection::factory()->create([
            'form_id' => $form->id,
            'segments' => json_encode([
                'fields'
            ]),
        ]);

        FormQuestion::factory()->create([
            'form_id' => $form->id,
            'form_section_id' => $section->id,
            'type' => 'text',
            'name' => 'foo',
            'validation' => [
                'required'
            ],
            'segment' => 'fields',
        ]);

        $resource = (new SiteResource([]))->toArray(request());

        $this->assertArrayHasKey('footer', $resource);
        $this->assertArrayHasKey('subscribe', $resource['footer']);
        $this->assertArrayHasKey('form', $resource['footer']['subscribe']);
        $this->assertEquals(5, $resource['footer']['subscribe']['form']['id']);
        $this->assertEquals('newsletter', $resource['footer']['subscribe']['form']['name']);

        $newsletter_form = $resource['footer']['subscribe']['form'];
        $this->assertEquals('newsletter', $newsletter_form['name']);
        $this->assertArrayHasKey('sections', $newsletter_form);
        $this->assertGreaterThan(0, count($newsletter_form['sections']));
        $this->assertNotNull($newsletter_form['sections'][0]->questions);
        $this->assertGreaterThan(0, count($newsletter_form['sections'][0]->questions));
        $this->assertEquals('foo', $newsletter_form['sections'][0]->questions[0]->name);
    }
}
