<?php

use App\Models\Product;
use App\Models\ProductLanguage;
use App\Models\ProductGroup;
use App\Models\ProductGroupLanguage;
use App\Models\Block;
use App\Models\BlockLanguage;
use App\Models\ListBoxItem;
use App\Models\ListBoxItemLanguage;
use App\Models\Row;
use App\Models\RowLanguage;

class ProductTableSeeder extends BaseSeeder
{

    private $blocksToInsert = [
        'blockListBox',
    ];

    private $availableLanguages = [];

    private $amountOfProducts = 5;

    private $createdProductsIds;

    /**
     * Run the database seeds.
     *
     * @return void
     */

    public function __construct()
    {
        $this->availableLanguages = getAvailableLanguages();
        $this->createdProductsIds = [];
    }

    public function run()
    {
        $this->command->info("Let's get this party started! Starting Product Seeders..");
        //Seeding Product Model Table first so later we can choose one for the product
        DB::beginTransaction();
        try {
            $this->call([ProductGroupTableSeeder::class]);
            factory(Product::class, $this->amountOfProducts)
                ->create()
                ->each(function ($product) {
                    $this->command->info("=== Starting Product Seeder ===");
                    // Get all multilangue objects
                    $availableLanguages = $this->availableLanguages;

                    // Create Website Objects
                    $websiteObject = $this->createWebsiteObject($product, 'product');

                    $product->websites()
                        ->save($websiteObject);

                    $mediaItemID = $this->createMediaItem();
                    $product->highlight_image_id = $mediaItemID;
    
                    $images = [];
                    for($i = 0; $i < 2; $i++) {
                        $images[] = $this->createMediaItem();
                    }

                    $product->otherImages()->sync($images);

                    $blocks = [];
                    foreach ($this->blocksToInsert as $blockType) {
                        $blocks[] = $this->_createBlock($blockType);
                    }

                    $product->productBlocks()->sync($blocks);

                    $productGroup = ProductGroup::inRandomOrder()->first();
                    $product->product_group_id = $productGroup->id;

                    $this->command->info("Assigned the product model ID '{$productGroup->id}' to the Product ID '{$product->id}'");

                    // Create language relationships
                    foreach ($availableLanguages as $langCode => $lang) {
                        $product->languages()
                            ->save(
                                factory(ProductLanguage::class)->make([
                                    'language_id' => $langCode,
                                    'product_id' => $product->id
                                ])
                            );

                        // Create Website Object Language
                        $this->createWebsiteObjectLanguage($websiteObject, $langCode);
                    }

                    $this->updateUri($websiteObject, 'product');

                    // Save all changes
                    $product->save();
                    $this->createdProductsIds[] = $product->id;
                    $this->command->info("Product created with ID: " . ' ' . $product->id);
                });
            $this->command->info("All products were created! now we need to assign each one of them some related products!");

            $createdProducts = Product::whereIn('id', $this->createdProductsIds)->get();
            $this->command->info("=== Starting to populate related products... ===");
            
            foreach($createdProducts as $product) {
                $relatedProducts = Product::WhereNotIn('id', [$product->id])->take(5)->get();
                $idsString = (String)$relatedProducts[0]->id;
                foreach($relatedProducts as $key => $relatedProduct) {
                    if ($key !== 0) {   
                        $idsString = $idsString . ', ' . $relatedProduct->id;
                    }
                }
                $product->relatedProducts()->sync($relatedProducts);
                $this->command->info('The product with ID ' . $product->id . ' have the following related products: ' . $idsString);
            }
            DB::commit();
        } catch(Throwable $exception) {
            DB::rollback();
            throw($exception);
        }

    }

    private function _createBlock($type) {
        $availableLanguages = $this->availableLanguages;
        $block = factory(Block::class)->create([
            "type" => $type,
        ]);

        if ($type === 'blockListBox') {
            $listBox = [];
            $listBox[] = $this->_createListBoxItems();
            $block->blockListBoxItems()->sync($listBox);
        }

        $websiteObject = $this->createWebsiteObject($block, 'blocks');

        $block->websites()
            ->save($websiteObject);

        foreach ($availableLanguages as $langCode => $lang) {

            $block->languages()
                ->save(
                    factory(BlockLanguage::class)->state($type)->make([
                        'language_id' => $langCode,
                        'block_id' => $block->id
                    ])
                );

            // Create Website Object Language
            $this->createWebsiteObjectLanguage($websiteObject, $langCode);
        }
        $this->updateUri($websiteObject, 'blocks');

        $block->save();

        return $block->id;

    }


    private function _createListBoxItems() {
        $availableLanguages = $this->availableLanguages;
        $listBoxItems = factory(ListBoxItem::class)->create([
            'button_type' => 'green',
        ]);

        for ($i = 0; $i < $this->amountOfProducts; $i++) {
            $rows[] = $this->_createRow();
        }
        $listBoxItems->rows()->sync($rows);

        $websiteObject = $this->createWebsiteObject($listBoxItems, 'listBoxItems');

        $listBoxItems->websites()
            ->save($websiteObject);

        foreach ($availableLanguages as $langCode => $lang) {

            $listBoxItems->languages()
                ->save(
                    factory(ListBoxItemLanguage::class)->make([
                        'language_id' => $langCode,
                        'list_box_item_id' => $listBoxItems->id
                    ])
                );

            // Create Website Object Language
            $this->createWebsiteObjectLanguage($websiteObject, $langCode);
        }
        $this->updateUri($websiteObject, 'listBoxItems');

        $listBoxItems->save();

        return $listBoxItems->id;

    }

    private function _createRow() {
        $availableLanguages = $this->availableLanguages;
        $row = factory(Row::class)->create();
        $websiteObject = $this->createWebsiteObject($row, 'rows');

        $row->websites()
            ->save($websiteObject);

        foreach ($availableLanguages as $langCode => $lang) {

            $row->languages()
                ->save(
                    factory(RowLanguage::class)->make([
                        'language_id' => $langCode,
                        'row_id' => $row->id
                    ])
                );

            // Create Website Object Language
            $this->createWebsiteObjectLanguage($websiteObject, $langCode);
        }
        $this->updateUri($websiteObject, 'rows');
        $row->save();
        return $row->id;
    }
}
