<?php

namespace App\Http\Middleware;

use App\Services\Database\SchemaUpdater;
use Closure;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Schema;
use Symfony\Component\HttpFoundation\Response;

class CheckSchemaMiddleware
{
    protected $schemaUpdater;

    public function __construct(SchemaUpdater $schemaUpdater)
    {
        $this->schemaUpdater = $schemaUpdater;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        /************** version 1.8 *************/
        // add tabs column to products tabl (added in v1.8)
        $this->schemaUpdater->addColumnToTable('products', 'tabs', 'text', [
            'nullable' => true,
        ], 'warnings');
        // add guide column to products table
        $this->schemaUpdater->addColumnToTable('products', 'guide', 'text', [
            'nullable' => true,
        ], 'warnings');
        // add send_time column to inventories table
        $this->schemaUpdater->addColumnToTable('inventories', 'send_time', 'string', [
            'nullable' => true,
        ], 'image');

        /************* version 2.1 *************/
        // add model_3d column to products table
        $this->schemaUpdater->addColumnToTable('products', 'model_3d', 'text', [
            'nullable' => true,
        ], 'videos');
        // add purchase_price column to inventories table
        $this->schemaUpdater->addColumnToTable('inventories', 'purchase_price', 'unsignedBigInteger', [
            'nullable' => true,
        ], 'weight');
        // add original column to inventories table
        $this->schemaUpdater->addColumnToTable('inventories', 'original', 'boolean', [
            'default' => true,
        ], 'max_sale');
        // add used column to inventories table
        $this->schemaUpdater->addColumnToTable('inventories', 'used', 'boolean', [
            'default' => false,
        ], 'max_sale');
        // add return_response column to transactions table
        $this->schemaUpdater->addColumnToTable('transactions', 'return_response', 'text', [
            'nullable' => true,
        ], 'gateway_reference_id');
        // add payment_transaction_uuid column to order_groups table
        $this->schemaUpdater->addColumnToTable('order_groups', 'payment_transaction_uuid', 'text', [
            'nullable' => true,
        ], 'uuid');

        /************* version 2.6 *************/
        // add description column to inventories table
        $this->schemaUpdater->addColumnToTable('inventories', 'description', 'text', [
            'nullable' => true,
        ], 'image');

        /************* version 3.1 *************/
        // add category_product table
        $this->schemaUpdater->addTable(
            'category_product',
            [
                [
                    'name' => 'product_id',
                    'type' => 'unsignedBigInteger',
                    'attributes' => ['index' => true],
                    'foreign' => [
                        'references' => 'id',
                        'on' => 'products',
                        'onDelete' => 'cascade',
                    ],
                ],
                [
                    'name' => 'category_id',
                    'type' => 'unsignedBigInteger',
                    'attributes' => ['index' => true],
                    'foreign' => [
                        'references' => 'id',
                        'on' => 'product_categories',
                        'onDelete' => 'cascade',
                    ],
                ],
            ],
            false,
            false
        );
        $this->schemaUpdater->addCompositeUnique(
            'category_product',
            ['product_id', 'category_id']
        );
        // add is_update_with_currency column to inventories
        $this->schemaUpdater->addColumnToTable('inventories', 'is_update_with_currency', 'boolean', [
            'default' => false,
        ], 'discount_expire');
        // add currency_price column to inventories
        $this->schemaUpdater->addColumnToTable('inventories', 'currency_price', 'double', [
            'nullable' => true,
        ], 'is_update_with_currency');
        // add currency_discount_price column to inventories
        $this->schemaUpdater->addColumnToTable('inventories', 'currency_discount_price', 'double', [
            'nullable' => true,
        ], 'currency_price');
        // set used column attributes to nullable in inventories table
        $this->schemaUpdater->EditColumnInTable('inventories', 'used', [
            'type' => 'boolean',
            'attributes' => [
                'nullable' => true,
            ],
        ]);
        // set original column attributes to nullable in inventories table
        $this->schemaUpdater->EditColumnInTable('inventories', 'original', [
            'type' => 'boolean',
            'attributes' => [
                'nullable' => true,
            ],
        ]);
        // add exchange_rate column to payment_metas
        $this->schemaUpdater->addColumnToTable('payment_metas', 'exchange_rate', 'unsignedBigInteger', [
            'nullable' => true,
        ], 'abandoned_cart');
        // set content column type to longtext in articles table
        $this->schemaUpdater->EditColumnInTable('articles', 'content', [
            'type' => 'longtext',
            'attributes' => [
                'nullable' => true,
            ],
        ]);
        // add options column to inventories
        $this->schemaUpdater->addColumnToTable('inventories', 'options', 'text', [
            'nullable' => true,
        ], 'discount_tree');
        // add options column to consignment_items
        $this->schemaUpdater->addColumnToTable('consignment_items', 'options', 'text', [
            'nullable' => true,
        ], 'props');
        // add filters table
        $this->schemaUpdater->addTable(
            'filters',
            [
                [
                    'name' => 'title',
                    'type' => 'string',
                ]
            ],
            true,
            true
        );
        // add filter_keys table
        $this->schemaUpdater->addTable(
            'filter_keys',
            [
                [
                    'name' => 'filter_id',
                    'type' => 'unsignedBigInteger',
                    'attributes' => ['index' => true],
                    'foreign' => [
                        'references' => 'id',
                        'on' => 'filters',
                        'onDelete' => 'cascade',
                    ],
                ],
                [
                    'name' => 'title',
                    'type' => 'string',
                ]
            ],
            true,
            true
        );
        // add filter_values table
        $this->schemaUpdater->addTable(
            'filter_values',
            [
                [
                    'name' => 'filter_key_id',
                    'type' => 'unsignedBigInteger',
                    'attributes' => [
                        'index' => true,
                        'unique_together' => ['product_id']
                    ],
                    'foreign' => [
                        'references' => 'id',
                        'on' => 'filter_keys',
                        'onDelete' => 'cascade',
                    ],
                ],
                [
                    'name' => 'product_id',
                    'type' => 'unsignedBigInteger',
                    'attributes' => [
                        'index' => true,
                        'unique_together' => ['filter_key_id']
                    ],
                    'foreign' => [
                        'references' => 'id',
                        'on' => 'products',
                        'onDelete' => 'cascade',
                    ],
                ],
                [
                    'name' => 'value',
                    'type' => 'string',
                ]
            ],
            true,
            true
        );
        // delete post_period from payment_metas table
        $this->schemaUpdater->DeleteColumnFromTable('payment_metas', 'post_period');
        // add receive_in_person_period column to payment_metas table
        $this->schemaUpdater->addColumnToTable('payment_metas', 'receive_in_person_period', 'text', [
            'nullable' => true,
        ], 'reception_centers_addresses');
        // add send_time column to consignments table
        $this->schemaUpdater->addColumnToTable('consignments', 'send_time', 'string', [
            'nullable' => true,
        ], 'send_method');
        // delete delivery_date from orders table
        $this->schemaUpdater->DeleteColumnFromTable('orders', 'delivery_date');
        // add send_time column to consignments table
        $this->schemaUpdater->addColumnToTable('orders', 'send_time', 'string', [
            'nullable' => true,
        ], 'send_method');

        /************* version 4.2 *************/
        // add with_password column to users table
        $this->schemaUpdater->addColumnToTable('users', 'with_password', 'boolean', [
            'default' => false,
        ], 'password');
        // add is_update column to inventories table
        $this->schemaUpdater->addColumnToTable('inventories', 'is_update', 'boolean', [
            'default' => true,
        ], 'send_time');
        // add receive_in_person_status column to payment_metas table
        $this->schemaUpdater->addColumnToTable('payment_metas', 'receive_in_person_status', 'boolean', [
            'default' => true,
        ], 'reception_centers_addresses');
        // inventories table indexes
        $this->schemaUpdater->addIndexToTable('inventories', ['product_id', 'status', 'count', 'discount_price'], 'idx_inv_product_status_count_discount');
        // stores table indexes
        $this->schemaUpdater->addIndexToTable('stores', 'status', 'idx_stores_status');
        // products table indexes
        $this->schemaUpdater->addIndexToTable('products', ['status', 'created_at'], 'idx_products_status_created');
        $this->schemaUpdater->addIndexToTable('products', 'view_count', 'idx_products_view_count');
        $this->schemaUpdater->addIndexToTable('products', ['status', 'is_vip'], 'idx_products_status_is_vip');
        $this->schemaUpdater->addIndexToTable('products', ['status', 'category_id'], 'idx_products_status_category');
        // consignment_items table indexes
        $this->schemaUpdater->addIndexToTable('consignment_items', ['product_id', 'status', 'count'], 'idx_consignment_product_status_count');
        // product_comments table indexes
        $this->schemaUpdater->addIndexToTable('product_comments', ['product_id', 'status', 'rating', 'created_at'], 'idx_comments_prod_status_rating_date');
        // questions table indexes
        $this->schemaUpdater->addIndexToTable('questions', ['product_id', 'status', 'created_at'], 'idx_questions_prod_status_created');
        // inventory_props table indexes
        $this->schemaUpdater->addIndexToTable('inventory_props', 'child', 'idx_inventory_props_child');
        // product_product_tag table indexes
        $this->schemaUpdater->addIndexToTable('product_product_tag', 'product_id', 'idx_ppt_product_id');
        // add start_process column to orders table
        $this->schemaUpdater->addColumnToTable('orders', 'start_process', 'boolean', [
            'default' => false,
        ], 'abandoned_cart');
        // add va_tax_percent column to orders table
        $this->schemaUpdater->addColumnToTable('orders', 'va_tax_percent', 'unsignedBigInteger', [
            'nullable' => true,
            'default' => null,
        ], 'discount');
        // add receipt_file_id column to order_groups table
        $this->schemaUpdater->addColumnToTable('order_groups', 'receipt_file_id', 'string', [
            'nullable' => true,
            'default' => null,
        ], 'payment_transaction_uuid');
        // add type column to order_groups table
        $this->schemaUpdater->addColumnToTable('order_groups', 'type', 'string', [
            'nullable' => true,
            'default' => null,
        ], 'receipt_file_id');
        // add payment_status column to order_groups table
        $this->schemaUpdater->addColumnToTable('order_groups', 'payment_status', 'string', [
            'nullable' => false,
            'default' => 'accepted',
        ], 'type');
        // add paid_by column to prefactors table
        $this->schemaUpdater->addColumnToTable('prefactors', 'paid_by', 'string', [
            'nullable' => true,
            'default' => null,
        ], 'title');

        return $next($request);
    }
}