Error executing query {
  text: 'SELECT c.id, c.name, c.main_category_id, mc.name AS main_category_name\n' +
    '         FROM categories c\n' +
    '         JOIN main_categories mc ON c.main_category_id = mc.id\n' +
    '         WHERE c.id = ANY($1::int[])',
  error: error: relation "main_categories" does not exist
      at /home/mustafakareem04/WebstormProjects/naayback/node_modules/pg/lib/client.js:526:17
      at processTicksAndRejections (node:internal/process/task_queues:95:5) {
    length: 115,
    severity: 'ERROR',
    code: '42P01',
    detail: undefined,
    hint: undefined,
    position: '113',
    internalPosition: undefined,
    internalQuery: undefined,
    where: undefined,
    schema: undefined,
    table: undefined,
    column: undefined,
    dataType: undefined,
    constraint: undefined,
    file: 'parse_relation.c',
    line: '1449',
    routine: 'parserOpenTable'
  }
}
Error updating product: error: relation "main_categories" does not exist
    at /home/mustafakareem04/WebstormProjects/naayback/node_modules/pg/lib/client.js:526:17
    at processTicksAndRejections (node:internal/process/task_queues:95:5) {
  length: 115,
  severity: 'ERROR',
  code: '42P01',
  detail: undefined,
  hint: undefined,
  position: '113',
  internalPosition: undefined,
  internalQuery: undefined,
  where: undefined,
  schema: undefined,
  table: undefined,
  column: undefined,
  dataType: undefined,
  constraint: undefined,
  file: 'parse_relation.c',
  line: '1449',
  routine: 'parserOpenTable'
}
PUT /products/2 500 1453.280 ms - 33


export const updateProduct = async (req: Request, res: Response) => {
    const { id } = req.params;
    const productData: UpdateProductInput = req.body;
    const productId: number = parseInt(id, 10);

    if (isNaN(productId)) {
        return res.status(400).json({ error: 'Invalid product ID' });
    }

    try {
        await query('BEGIN');

        // Adjust product price if necessary
        let adjustedProductPrice: number = productData.price;
        if (adjustedProductPrice < 1000) {
            adjustedProductPrice = parseFloat((adjustedProductPrice * 1000).toFixed(2));
        }

        // Update product details
        const result = await query(
            `
            UPDATE products 
            SET 
                name = $1, 
                description = $2, 
                brand_id = $3, 
                has_color = $4, 
                has_size = $5, 
                product_type = $6, 
                price = $7, 
                qty = $8, 
                updated_at = CURRENT_TIMESTAMP 
            WHERE id = $9 
            RETURNING *
            `,
            [
                productData.name,
                productData.description,
                productData.brand_id,
                productData.has_color,
                productData.has_size,
                productData.product_type,
                adjustedProductPrice,
                productData.qty,
                productId
            ]
        );

        if (result.rows.length === 0) {
            await query('ROLLBACK');
            return res.status(404).json({ error: 'Product not found' });
        }

        // Delete existing associations and data
        await query('DELETE FROM product_categories WHERE product_id = $1', [productId]);
        await query('DELETE FROM images WHERE product_id = $1', [productId]);

        // Get existing colors and sizes
        const existingColorsResult = await query('SELECT id FROM colors WHERE product_id = $1', [productId]);
        const existingColorIds = new Set(existingColorsResult.rows.map((row: any) => row.id));

        const existingSizesResult = await query('SELECT id FROM sizes WHERE product_id = $1', [productId]);
        const existingSizeIds = new Set(existingSizesResult.rows.map((row: any) => row.id));

        // Determine colors and sizes to delete
        const updatedColorIds = new Set(
            productData.colors
                ?.map((color: ColorInput) => color.id)
                .filter((id: number | undefined): id is number => typeof id === 'number') || []
        );
        const colorsToDelete = [...existingColorIds].filter(id => !updatedColorIds.has(id));

        const updatedSizeIds = new Set([
            ...(productData.sizes
                ?.map((size: SizeInput) => size.id)
                .filter((id: number | undefined): id is number => typeof id === 'number') || []),
            ...(productData.colors?.flatMap((color: ColorInput) =>
                color.sizes.map((size: SizeInput) => size.id).filter((id: number | undefined): id is number => typeof id === 'number')
            ) || [])
        ]);
        const sizesToDelete = [...existingSizeIds].filter(id => !updatedSizeIds.has(id));

        // Delete colors and associated sizes and images
        for (const colorId of colorsToDelete) {
            await query('DELETE FROM sizes WHERE color_id = $1', [colorId]);
            await query('DELETE FROM images WHERE color_id = $1', [colorId]);
            await query('DELETE FROM colors WHERE id = $1', [colorId]);
        }

        // Delete sizes and associated images
        for (const sizeId of sizesToDelete) {
            await query('DELETE FROM images WHERE size_id = $1', [sizeId]);
            await query('DELETE FROM sizes WHERE id = $1', [sizeId]);
        }

        // Insert category associations
        if (productData.category_ids.length > 0) {
            const categoryInsertPromises = productData.category_ids.map((categoryId: number) =>
                query(
                    `INSERT INTO product_categories (product_id, category_id) 
                     VALUES ($1, $2)`,
                    [productId, categoryId]
                )
            );
            await Promise.all(categoryInsertPromises);
        }

        // Insert images
        let insertedImages: Image[] = [];
        if (productData.images.length > 0) {
            const imagesInsertPromises = productData.images.map((image: ImageInput) =>
                query(
                    `INSERT INTO images (product_id, url, color_id, size_id)
                     VALUES ($1, $2, $3, $4)
                     RETURNING id, url, color_id, size_id`,
                    [productId, image.url, image.color_id || null, image.size_id || null]
                )
            );
            const insertedImagesResults = await Promise.all(imagesInsertPromises);
            insertedImages = insertedImagesResults.map((imgResult: any) => ({
                id: imgResult.rows[0].id,
                url: imgResult.rows[0].url,
                color_id: imgResult.rows[0].color_id,
                size_id: imgResult.rows[0].size_id
            }));
        }

        // Insert colors and sizes
        let insertedColors: number[] = [];
        let insertedSizes: number[] = [];
        if (productData.has_color && productData.colors && productData.colors.length > 0) {
            for (const colorInput of productData.colors) {
                // Adjust color price if necessary
                let adjustedColorPrice: number = colorInput.price;
                if (adjustedColorPrice < 1000) {
                    adjustedColorPrice = parseFloat((adjustedColorPrice * 1000).toFixed(2));
                }

                // Insert or Update color
                let colorId: number;
                if (colorInput.id) {
                    // Update existing color
                    await query(
                        `
                        UPDATE colors 
                        SET 
                            name = $1, 
                            price = $2, 
                            qty = $3, 
                            sold = $4, 
                            has_size = $5 
                        WHERE id = $6
                        `,
                        [
                            colorInput.name,
                            adjustedColorPrice,
                            colorInput.qty,
                            colorInput.sold || 0,
                            colorInput.has_size,
                            colorInput.id
                        ]
                    );
                    colorId = colorInput.id;
                } else {
                    // Insert new color
                    const colorResult = await query(
                        `
                        INSERT INTO colors 
                            (product_id, name, price, qty, sold, has_size)
                        VALUES 
                            ($1, $2, $3, $4, 0, $5)
                        RETURNING id
                        `,
                        [productId, colorInput.name, adjustedColorPrice, colorInput.qty, colorInput.has_size]
                    );
                    colorId = colorResult.rows[0].id;
                    insertedColors.push(colorId);
                }

                // Insert color images
                if (colorInput.images.length > 0) {
                    const colorImagesInsertPromises = colorInput.images.map((image: ImageInput) =>
                        query(
                            `
                            INSERT INTO images 
                                (product_id, color_id, url, size_id)
                            VALUES 
                                ($1, $2, $3, $4)
                            RETURNING id, url, color_id, size_id
                            `,
                            [productId, colorId, image.url, image.size_id || null]
                        )
                    );
                    await Promise.all(colorImagesInsertPromises);
                }

                // Insert sizes within color
                if (colorInput.has_size && colorInput.sizes && colorInput.sizes.length > 0) {
                    for (const sizeInput of colorInput.sizes) {
                        // Adjust size price if necessary
                        let adjustedSizePrice: number = sizeInput.price;
                        if (adjustedSizePrice < 1000) {
                            adjustedSizePrice = parseFloat((adjustedSizePrice * 1000).toFixed(2));
                        }

                        // Insert or Update size
                        let sizeId: number;
                        if (sizeInput.id) {
                            // Update existing size
                            await query(
                                `
                                UPDATE sizes 
                                SET 
                                    name = $1, 
                                    price = $2, 
                                    qty = $3, 
                                    sold = $4, 
                                    color_id = $5 
                                WHERE id = $6
                                `,
                                [
                                    sizeInput.name,
                                    adjustedSizePrice,
                                    sizeInput.qty,
                                    sizeInput.sold || 0,
                                    colorId,
                                    sizeInput.id
                                ]
                            );
                            sizeId = sizeInput.id;
                        } else {
                            // Insert new size
                            const sizeResult = await query(
                                `
                                INSERT INTO sizes 
                                    (product_id, color_id, name, price, qty, sold)
                                VALUES 
                                    ($1, $2, $3, $4, $5, 0)
                                RETURNING id
                                `,
                                [productId, colorId, sizeInput.name, adjustedSizePrice, sizeInput.qty]
                            );
                            sizeId = sizeResult.rows[0].id;
                            insertedSizes.push(sizeId);
                        }

                        // Insert size images
                        if (sizeInput.images.length > 0) {
                            const sizeImagesInsertPromises = sizeInput.images.map((image: ImageInput) =>
                                query(
                                    `
                                    INSERT INTO images 
                                        (product_id, color_id, size_id, url)
                                    VALUES 
                                        ($1, $2, $3, $4)
                                    RETURNING id, url, color_id, size_id
                                    `,
                                    [productId, colorId, sizeId, image.url]
                                )
                            );
                            await Promise.all(sizeImagesInsertPromises);
                        }
                    }
                }
            }
        } else if (productData.has_size && productData.sizes && productData.sizes.length > 0) {
            for (const sizeInput of productData.sizes) {
                // Adjust size price if necessary
                let adjustedSizePrice: number = sizeInput.price;
                if (adjustedSizePrice < 1000) {
                    adjustedSizePrice = parseFloat((adjustedSizePrice * 1000).toFixed(2));
                }

                // Insert or Update size
                let sizeId: number;
                if (sizeInput.id) {
                    // Update existing size
                    await query(
                        `
                        UPDATE sizes 
                        SET 
                            name = $1, 
                            price = $2, 
                            qty = $3, 
                            sold = $4 
                        WHERE id = $5
                        `,
                        [
                            sizeInput.name,
                            adjustedSizePrice,
                            sizeInput.qty,
                            sizeInput.sold || 0,
                            sizeInput.id
                        ]
                    );
                    sizeId = sizeInput.id;
                } else {
                    // Insert new size
                    const sizeResult = await query(
                        `
                        INSERT INTO sizes 
                            (product_id, name, price, qty, sold)
                        VALUES 
                            ($1, $2, $3, $4, 0)
                        RETURNING id
                        `,
                        [productId, sizeInput.name, adjustedSizePrice, sizeInput.qty]
                    );
                    sizeId = sizeResult.rows[0].id;
                    insertedSizes.push(sizeId);
                }

                // Insert size images
                if (sizeInput.images.length > 0) {
                    const sizeImagesInsertPromises = sizeInput.images.map((image: ImageInput) =>
                        query(
                            `
                            INSERT INTO images 
                                (product_id, size_id, url)
                            VALUES 
                                ($1, $2, $3)
                            RETURNING id, url, color_id, size_id
                            `,
                            [productId, sizeId, image.url]
                        )
                    );
                    await Promise.all(sizeImagesInsertPromises);
                }
            }
        }

        // Fetch and populate categories with details
        const categories = await fetchCategoryDetails(productData.category_ids);

        // Construct the updated product object as it would appear in the cache
        const updatedProduct: Product = {
            id: productId,
            name: productData.name,
            description: productData.description,
            brand_id: productData.brand_id,
            has_color: productData.has_color,
            has_size: productData.has_size,
            product_type: productData.product_type,
            price: adjustedProductPrice,
            qty: productData.qty,
            sold: 0, // Assuming sold remains unchanged; adjust if necessary
            created_at: result.rows[0].created_at.toISOString(),
            updated_at: new Date().toISOString(),
            categories: categories,
            colors: productData.has_color && productData.colors
                ? productData.colors.map((colorInput, index) => ({
                    id: colorInput.id || insertedColors[index],
                    name: colorInput.name,
                    price: colorInput.price,
                    qty: colorInput.qty,
                    sold: colorInput.sold || 0,
                    has_size: colorInput.has_size,
                    sizes: colorInput.has_size && colorInput.sizes
                        ? colorInput.sizes.map((sizeInput, sIndex) => ({
                            id: sizeInput.id || insertedSizes[sIndex],
                            name: sizeInput.name,
                            price: sizeInput.price,
                            qty: sizeInput.qty,
                            sold: sizeInput.sold || 0,
                            color_id: colorInput.id || insertedColors[index],
                            images: sizeInput.images.map(img => img.url)
                        }))
                        : [],
                    images: colorInput.images.map(img => img.url)
                }))
                : [],
            sizes: productData.has_size && !productData.has_color && productData.sizes
                ? productData.sizes.map((sizeInput, index) => ({
                    id: sizeInput.id || insertedSizes[index],
                    name: sizeInput.name,
                    price: sizeInput.price,
                    qty: sizeInput.qty,
                    sold: sizeInput.sold || 0,
                    color_id: null,
                    images: sizeInput.images.map(img => img.url)
                }))
                : [],
            images: insertedImages
        };

        // Update the cache
        updateProductInCache(updatedProduct);

        await query('COMMIT');
        res.json({ message: 'Product updated successfully', product: updatedProduct });
    } catch (error) {
        await query('ROLLBACK');
        console.error('Error updating product:', error);
        res.status(500).json({ error: 'Internal server error' });
    }
};

the database:
await client.query('BEGIN');

        // 1. Create users table
        await client.query(`
            CREATE TABLE IF NOT EXISTS users (
                user_id SERIAL PRIMARY KEY,
                name VARCHAR(255) NOT NULL,
                email VARCHAR(255) UNIQUE NOT NULL,
                password VARCHAR(255) NOT NULL,
                created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
                last_login TIMESTAMPTZ,
                is_active BOOLEAN DEFAULT true
            );
        `);

        // 2. Create brands table
        await client.query(`
            CREATE TABLE IF NOT EXISTS brands (
                id SERIAL PRIMARY KEY,
                name VARCHAR(255) UNIQUE NOT NULL,
                description TEXT,
                created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
            );
        `);

        // 3. Create categories table
        await client.query(`
            CREATE TABLE IF NOT EXISTS categories (
                id SERIAL PRIMARY KEY,
                name VARCHAR(255) UNIQUE NOT NULL
            );
        `);

        // 4. Create subcategories table
        await client.query(`
            CREATE TABLE IF NOT EXISTS subcategories (
                id SERIAL PRIMARY KEY,
                name VARCHAR(255) NOT NULL,
                category_id INTEGER NOT NULL,
                FOREIGN KEY (category_id) REFERENCES categories (id) ON DELETE CASCADE,
                UNIQUE(name, category_id)
            );
        `);

        // 5. Create products table with foreign key to brands
        await client.query(`
            CREATE TABLE IF NOT EXISTS products (
                id SERIAL PRIMARY KEY,
                name TEXT NOT NULL,
                description TEXT NOT NULL,
                brand_id INTEGER NOT NULL,
                has_color BOOLEAN NOT NULL DEFAULT false,
                has_size BOOLEAN NOT NULL DEFAULT false,
                product_type VARCHAR(10) NOT NULL,
                price NUMERIC(10, 2) CHECK (price >= 0),
                qty INTEGER CHECK (qty >= 0),
                created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
                sold INTEGER NOT NULL DEFAULT 0 CHECK (sold >= 0),
                FOREIGN KEY (brand_id) REFERENCES brands (id) ON DELETE RESTRICT
                -- Changed from ON DELETE SET NULL to ON DELETE RESTRICT to maintain NOT NULL
            );
        `);

        // 6. Create colors table with foreign key to products
        await client.query(`
            CREATE TABLE IF NOT EXISTS colors (
                id SERIAL PRIMARY KEY,
                product_id INTEGER NOT NULL,
                name VARCHAR(255) NOT NULL,
                has_size BOOLEAN NOT NULL DEFAULT false,
                price NUMERIC(10,2) CHECK (price >= 0),
                qty INTEGER NOT NULL CHECK (qty >= 0),
                sold INTEGER NOT NULL DEFAULT 0 CHECK (sold >= 0),
                FOREIGN KEY (product_id) REFERENCES products (id) ON DELETE CASCADE,
                UNIQUE(name, product_id)
            );
        `);

        // 7. Create sizes table with foreign keys to products and colors
        await client.query(`
            CREATE TABLE IF NOT EXISTS sizes (
                id SERIAL PRIMARY KEY,
                product_id INTEGER NOT NULL,
                color_id INTEGER,
                name VARCHAR(255) NOT NULL,
                price NUMERIC(10,2) CHECK (price >= 0),
                qty INTEGER CHECK (qty >= 0),
                sold INTEGER NOT NULL DEFAULT 0 CHECK (sold >= 0),
                FOREIGN KEY (product_id) REFERENCES products (id) ON DELETE CASCADE,
                FOREIGN KEY (color_id) REFERENCES colors (id) ON DELETE SET NULL,
                UNIQUE(name, color_id, product_id)
            );
        `);

        // 8. Create images table with foreign keys to products, colors, and sizes
        await client.query(`
            CREATE TABLE IF NOT EXISTS images (
                id SERIAL PRIMARY KEY,
                product_id INTEGER NOT NULL,
                color_id INTEGER,
                size_id INTEGER,
                url VARCHAR(255) NOT NULL,
                FOREIGN KEY (product_id) REFERENCES products (id) ON DELETE CASCADE,
                FOREIGN KEY (color_id) REFERENCES colors (id) ON DELETE SET NULL,
                FOREIGN KEY (size_id) REFERENCES sizes (id) ON DELETE SET NULL
            );
        `);

        // 9. Create coupons table
        await client.query(`
            CREATE TABLE IF NOT EXISTS coupons (
                id SERIAL PRIMARY KEY,
                code VARCHAR(20) UNIQUE NOT NULL,
                name VARCHAR(255) NOT NULL,
                description VARCHAR(255),
                discount_amount NUMERIC(10,2),
                discount_percentage NUMERIC(5,2) CHECK (discount_percentage >= 0 AND discount_percentage <= 100),
                start_date DATE NOT NULL,
                end_date DATE NOT NULL,
                usage_limit INTEGER NOT NULL CHECK (usage_limit >= 0),
                min_purchase_amount NUMERIC(10,2) NOT NULL CHECK (min_purchase_amount >= 0),
                max_discount_amount NUMERIC(10,2) CHECK (max_discount_amount >= 0),
                is_active BOOLEAN DEFAULT true,
                coupon_image VARCHAR(255),
                created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
                updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL
            );
        `);

        // 10. Create address table
        await client.query(`
            CREATE TABLE IF NOT EXISTS address (
                id SERIAL PRIMARY KEY,
                user_id INTEGER NOT NULL,
                full_name VARCHAR(255) NOT NULL,
                governorate VARCHAR(255) NOT NULL,
                city VARCHAR(255) NOT NULL,
                address TEXT NOT NULL,
                closest_point TEXT,
                phone_number VARCHAR(20) NOT NULL,
                type VARCHAR(20),
                FOREIGN KEY (user_id) REFERENCES users (user_id) ON DELETE CASCADE
            );
        `);

        // 11. Create product_categories table with composite primary key
        await client.query(`
            CREATE TABLE IF NOT EXISTS product_categories (
                product_id INTEGER NOT NULL,
                category_id INTEGER NOT NULL,
                PRIMARY KEY (product_id, category_id),
                FOREIGN KEY (product_id) REFERENCES products (id) ON DELETE CASCADE,
                FOREIGN KEY (category_id) REFERENCES categories (id) ON DELETE CASCADE
            );
        `);

        // 12. Create carts table with foreign keys to users and coupons
        await client.query(`
            CREATE TABLE IF NOT EXISTS carts (
                id SERIAL PRIMARY KEY,
                user_id INTEGER,
                status VARCHAR(20) NOT NULL DEFAULT 'active',
                notes VARCHAR(255),
                full_name VARCHAR(255) NOT NULL,
                governorate VARCHAR(50) NOT NULL,
                city VARCHAR(100) NOT NULL,
                address TEXT NOT NULL,
                closest_point TEXT,
                phone_number VARCHAR(20) NOT NULL,
                type VARCHAR(20),
                created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
                coupon_id INTEGER,
                updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY (user_id) REFERENCES users (user_id) ON DELETE SET NULL,
                FOREIGN KEY (coupon_id) REFERENCES coupons (id) ON DELETE SET NULL
            );
        `);

        // 13. Create cart_items table with foreign keys to carts, products, sizes, and colors
        await client.query(`
            CREATE TABLE IF NOT EXISTS cart_items (
                id SERIAL PRIMARY KEY,
                cart_id INTEGER NOT NULL,
                product_id INTEGER NOT NULL,
                size_id INTEGER,
                color_id INTEGER,
                quantity INTEGER NOT NULL CHECK (quantity > 0),
                FOREIGN KEY (cart_id) REFERENCES carts (id) ON DELETE CASCADE,
                FOREIGN KEY (product_id) REFERENCES products (id) ON DELETE CASCADE,
                FOREIGN KEY (size_id) REFERENCES sizes (id) ON DELETE SET NULL,
                FOREIGN KEY (color_id) REFERENCES colors (id) ON DELETE SET NULL,
                UNIQUE(cart_id, product_id, size_id, color_id)
            );
        `);

        // 14. Enhance Tables with Indexes

        // Foreign Key Indexes
        await client.query(`CREATE INDEX IF NOT EXISTS idx_products_brand_id ON products (brand_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_images_product_id ON images (product_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_images_color_id ON images (color_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_images_size_id ON images (size_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_colors_product_id ON colors (product_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_sizes_product_id ON sizes (product_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_sizes_color_id ON sizes (color_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_product_categories_category_id ON product_categories (category_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_carts_user_id ON carts (user_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_carts_coupon_id ON carts (coupon_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_cart_items_cart_id ON cart_items (cart_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_cart_items_product_id ON cart_items (product_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_cart_items_size_id ON cart_items (size_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_cart_items_color_id ON cart_items (color_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_address_user_id ON address (user_id);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_coupons_code ON coupons (code);`);

        // Commonly Searched Columns Indexes
        await client.query(`CREATE INDEX IF NOT EXISTS idx_products_name ON products (name);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_categories_name ON categories (name);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_subcategories_name ON subcategories (name);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_colors_name ON colors (name);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_sizes_name ON sizes (name);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_carts_status ON carts (status);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_coupons_name ON coupons (name);`);
        await client.query(`CREATE INDEX IF NOT EXISTS idx_address_city ON address (city);`);

example response:
{"products":[{"id":2,"name":"test","description":"test","brand_id":95,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-09-24T09:23:26.682Z","updated_at":"2024-09-24T09:23:26.682Z","categories":[{"id":178,"name":"Body Cleansers","main_category_id":2,"main_category_name":"Body Care"}],"colors":[],"sizes":[{"id":3,"name":"20ml","price":20000,"qty":10,"sold":0,"color_id":null,"images":[]}],"images":[]},{"id":6,"name":"‏Anua Heartleaf Pore Clay Pack","description":"يقوم هذا القناع الطيني الكريمي بأمتصاص الزهم الزائد و إزالة الرؤوس السوداء بشكل فعال داخل المسام بسبب احتوائه Houttuynia Cordata الذي يتحكم في الدهون\nيحتوي على الكاولين لامتصاص الدهون\nيحتوي على مادة البنتونيت لتضييق المسام\nيحتوي على كيرسيتينول و هو المكون الرئيسي لأوراق القلب يوفر تهدئة البشرة ويتحكم في الدهون الزائدة لإزالة مشاكل المسام\nيعمل ايضا على إذابة خلايا الجلد الميتة القديمة على الجلد بلطف دون أي تهيج إضافة إلى تنعيم البشرة","brand_id":117,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-23T21:51:27.907Z","updated_at":"2024-09-10T13:58:17.276Z","categories":[{"id":175,"name":"Masks","main_category_id":1,"main_category_name":"Face Care"}],"colors":[],"sizes":[{"id":1418,"name":"100 ML","price":22000,"qty":118,"sold":0,"color_id":null,"images":["1048.webp"]}],"images":[{"id":1588,"url":"1048.webp","color_id":null,"size_id":1418}]},{"id":7,"name":"‏Anua Heartleaf Pore Control CleanSsing Oil","description":"غسول منظف زيتي بالهارت ليف للمسامات من انوا\nمنظف زيتي بتركيبة لا تسبب انسداد المسامات ويحتوي على زيوت نباتية (بما في ذلك زيت الجوجوبا وفاكهة الزيتون وبذور العنب)، ويخلص البشرة من الشوائب بشكل فعال مع ترك لمسة نهائية منتعشة ورطبة. مناسب للبشرة المعرضة للحبوب.\nمميزاته وفوائده:\n‏* non-comedogenic تركيبة لا تسد المسامات مناسبة للبشرة الدهنية والمعرضة للحبوب\n* مستخلص هارتليف (houttuynia cordata) معروف جيدًا بتأثيره المضاد للالتهابات والمهدئ للبشرة.\n* مزيل مكياج خفيف يساعد على إزالة الشوائب في المسامات.\n* لا يحتوي على أي مواد مهيجة.\n* يحافظ على رطوبة بشرتك بعد التنظيف.\n* يناسب جميع انواع البشرات حتى الحساسة.","brand_id":117,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-23T21:54:49.385Z","updated_at":"2024-09-23T15:58:27.136Z","categories":[{"id":168,"name":"Face Cleansers","main_category_id":1,"main_category_name":"Face Care"}],"colors":[],"sizes":[{"id":1428,"name":"200 ML","price":25000,"qty":100,"sold":0,"color_id":null,"images":["1049.webp"]}],"images":[{"id":24,"url":"1049.webp","color_id":null,"size_id":1428}]},{"id":8,"name":"‏ANUA Heartleaf Quercerinol Pore Deep Cleansing Foam","description":"غسول رغوي بالهارت ليف كيرسيتينول للتنظيف العميق للمسام من انوا \nتم تصميم رغوة التنظيف هذه خصيصا لأنواع البشرة المختلطة والدهنية ، واستهداف الدهون الزائدة وتنظيف المسام بشكل فعال عن طريق إزالة خلايا الجلد الميتة المتراكمة والشوائب\nمميزات وفوائد:\nيحتوي على مسحوق أوراق القلب المطحون ناعما ، مما يساعد على تطهير الأوساخ وخلايا الجلد الميتة من زوايا المسام.\nغني بالمكون المضاد للدهون الحاصل على براءة اختراع ، فهو يحافظ على شعور البشرة بالانتعاش بعد التنظيف ويساعد على معالجة مخاوف الدهون الزائدة.","brand_id":117,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-23T21:59:34.747Z","updated_at":"2024-09-23T17:08:29.990Z","categories":[{"id":168,"name":"Face Cleansers","main_category_id":1,"main_category_name":"Face Care"}],"colors":[],"sizes":[{"id":1429,"name":"150 ML","price":25000,"qty":127,"sold":0,"color_id":null,"images":["1050.webp"]}],"images":[{"id":33,"url":"1050.webp","color_id":null,"size_id":1429}]},{"id":9,"name":"‏La Roche Effaclar Astringent Lotion","description":"تونر للبشرة الدهنية و المعرضة للحبوب من la roche \n-يعمل على تقليل حجم المسام بشكل ملحوظ بعد إستخدامه بفضل مكوناته الفعٌالة التي تعمل على تنظيم الإفراز الدهني للوجه و تقشيره بلطف ويقلل من انسداد المسام المسببة لحب الشباب.\n-تلطيف البشرة وموازنة درجة الحموضة بعد خطوة التنظيف مما يعمل معادلة للبشره ولا يسبب جفاف للبشره \n-تنظيف عميق للمسام وإزالة بقايا الجلد الميت من مناطق الجلد التي غالبًا ما تُترك عند غسل وجهك.\n-تساعد المياه المعدنية La Roche-Posay على تهدئة البشرة وحمايتها ومضادات الأكسدة.","brand_id":70,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-24T12:29:54.092Z","updated_at":"2024-09-18T06:42:49.283Z","categories":[{"id":169,"name":"Toners","main_category_id":1,"main_category_name":"Face Care"}],"colors":[],"sizes":[{"id":1431,"name":"200 ml","price":25000,"qty":19,"sold":0,"color_id":null,"images":["1052.jpeg"]}],"images":[{"id":3283,"url":"1052.jpeg","color_id":null,"size_id":1431}]},{"id":11,"name":"Aveeno Daily Moisturising Hand Cream","description":"مرطب يد يومي من أفينو\nيتكون من دقيق الشوفان، تعمل هذه التركيبة سريعة الامتصاص على ترطيب البشرة لمدة 24 ساعة، فهو يساعد على حماية وتغذية اليد العادية إلى الجافة. يمنحك بشرة صحية وأكثر مرونة من الاستخدام الأول، لا يحتوي عطور و مناسب لبشرة اليد الحساسة.","brand_id":86,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-24T12:43:56.173Z","updated_at":"2024-09-10T18:04:29.869Z","categories":[{"id":163,"name":"Hand moisturiser","main_category_id":6,"main_category_name":"Hand Care"}],"colors":[],"sizes":[{"id":1430,"name":"75 ml","price":12000,"qty":10,"sold":0,"color_id":null,"images":["1056.jpeg"]}],"images":[{"id":1600,"url":"1056.jpeg","color_id":null,"size_id":1430}]},{"id":12,"name":"La Roche Posay Thermal Spring Water","description":"‏سبري ملطف ومرطب للبشره الحساسة المتهيجة بسبب العوامل الخارجية (الشمس ووسائل العناية بالبشرة وغيرها...) ويساعد على منع تقدم عمر الجلد. مضاد طبيعي للأكسدة.يمنح المزيج الفريد من المعادن والعناصر النادرة مثل السيلينيوم، ومياه الينابيع الحرارية من لاروش بوزيه خصائص مثبتة علميًا في الترطيب والنعومة ومضاد للأكسدة. تركيبة دقيقة. مناسب للكبار والأطفال.","brand_id":70,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-24T12:50:28.619Z","updated_at":"2024-09-17T18:17:11.779Z","categories":[{"id":193,"name":"Mist","main_category_id":1,"main_category_name":"Face Care"}],"colors":[],"sizes":[{"id":899,"name":"150 ml","price":15000,"qty":51,"sold":0,"color_id":null,"images":["1057.jpeg"]}],"images":[{"id":3232,"url":"1057.jpeg","color_id":null,"size_id":899}]},{"id":14,"name":"La Roche Posay Effaclar Medicated Acne Face Wash","description":"غسول منظف لحب الشباب من la roche posay.\nيزيل الزيوت الزائدة ويعمل على إزالة حب الشباب. \nيحتوي على:\n2٪ حمض الساليسيليك: معروف بخصائصه الفعالة في التقشير للمساعدة في تنظيف وتنقية ظهور المسام.\nحمض ليبو هيدروكسي: المعروف أيضًا باسم LHA ، وهو مشتق من حمض الساليسيليك ، وله خصائص تقشير وتجديد البشرة.\nالجلسرين: مشتق من مصادر نباتية ، وهو مرطب ممتاز. يساعد على ترطيب البشرة عن طريق امتصاص الماء من البيئة المحيطة.\nمناسب لجميع انواع البشرة","brand_id":70,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-24T13:02:33.887Z","updated_at":"2024-09-17T18:29:30.996Z","categories":[{"id":168,"name":"Face Cleansers","main_category_id":1,"main_category_name":"Face Care"}],"colors":[],"sizes":[{"id":1433,"name":"200 ml","price":30000,"qty":12,"sold":0,"color_id":null,"images":["1062.jpeg"]}],"images":[{"id":3234,"url":"1062.jpeg","color_id":null,"size_id":1433}]},{"id":21,"name":"La Roche Posay Anthelios Anti Shine Fresh Mist Spf50 Facial Sunscreen","description":"واقي شمس سبري شفاف يعطي أقصى حماية للوجه من الأشعة فوق البنفسجية الضارة, بعامل وقايه spf 50 يثبت المكياج و يقاوم المياه, يمتص في ثلاث ثواني و لا يترك علامات بيضاء ومضاد للدهون والتعرق \nيناسب جميع أنواع البشرة والبشرة الحساسة والبشرة التي لا تحتمل التعرض للشمس والمعروفة باسم حساسية الشمس.","brand_id":70,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-24T13:49:25.525Z","updated_at":"2024-09-23T12:12:41.239Z","categories":[{"id":173,"name":"Face Sunscreens","main_category_id":1,"main_category_name":"Face Care"}],"colors":[],"sizes":[{"id":586,"name":"75 ml","price":25000,"qty":73,"sold":0,"color_id":null,"images":["1069.jpeg"]}],"images":[{"id":7,"url":"1069.jpeg","color_id":null,"size_id":586}]},{"id":24,"name":"La Roche Posay Cicaplast Balm B5","description":"كريم سيكابلاست من لاروش بوساي\n-تهدئة البشرة المتهيجة خاصة بعد جلسات الديرما بن الديرما رولر  وجلسات ليزر \n-تعمل على الاصلاح  والحماية\nويساعد البشرة على التعافي من (التهيج ،التشقق ، والبقع الخشنه )\nمميزات المنتج :\nيعرف بانه كريم معالج سريع عند حدوث اي شي يسبب في تهيج او احمرار للبشره.. \nمناسب للحروق ولتحسس.","brand_id":70,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-24T13:58:32.728Z","updated_at":"2024-09-17T18:19:42.086Z","categories":[{"id":172,"name":"Face moisturiser","main_category_id":1,"main_category_name":"Face Care"}],"colors":[],"sizes":[{"id":587,"name":"40 ml","price":25000,"qty":141,"sold":-6,"color_id":null,"images":["1071.jpeg"]}],"images":[{"id":3233,"url":"1071.jpeg","color_id":null,"size_id":587}]},{"id":25,"name":"La Roche posay Cicaplast levres","description":"بلسم ملطف للشفاه من الجفاف ويحميها ويلطفها\nلعلاج التهاب و تشقق الشفتين الناتج من الجفاف حيث يقوم بترطيب واعادة نمو الطبقة الواقية للشفتين وإزالة الإسمرار واللون الغامق للشفتين\nحيث أنه يعمل على تكوين حاجز بتركيبته الفريدة المحتوية على 5% بانثينول لمنحك إنتعاش سريع، و البروتين الدهني (Mp_lipids) الذي يساعد على ترميم الحاجز الحامي للبشرة\nيمكن استخدامها للاطفال والكبار","brand_id":70,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-24T14:01:07.105Z","updated_at":"2024-09-17T07:47:45.902Z","categories":[{"id":153,"name":"Lip Balm","main_category_id":5,"main_category_name":"Lip Care"}],"colors":[],"sizes":[{"id":588,"name":"7.5 ml","price":15000,"qty":24,"sold":0,"color_id":null,"images":["1072.jpeg"]}],"images":[{"id":2914,"url":"1072.jpeg","color_id":null,"size_id":588}]},{"id":26,"name":"La Roche Posay Pure Vitamin C10 Serum","description":"سيروم فيتامين بتركيزC10 من الفيتامين النقي، محلول مضاد للتجاعيد ، يحتوي على فيتامين C  النقي ، وحمض الساليسيليك والنيوسينسين للكشف عن النضارة الكاملة للبشرة الحساسة .\nيعالج فقدان النضارة ، والبشرة الغير ،مستوية التجاعيد.\nسيروم فريد من نوعه مضاد لعلامات تقدم سن البشرة ومركّز بمكونات عالية من فيتامين C النقي ، مع حمض الساليسيليك والنسوسينسين الملطف ، مع درجة حموضة فسيولوجية ، للكشف عن النضارة الكاملة للبشرة الحساسة.\nعلى الفور، تبدو البشرة أكثر نعومة، نضارة و ترطيب.\nتقل التجاعيد والخطوط الدقيقة. كما لو تحولت، يبدو ملمس البشرة ولونها أكثر تناسقًا و تستعيد البشرة إشراقتها الكاملة.\nيطبق في الصباح على الوجه والعنق. تجنب منطقة العين. يستخدم مع واقي من الشمس يومي.","brand_id":70,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-24T14:04:30.261Z","updated_at":"2024-09-17T18:43:24.198Z","categories":[{"id":170,"name":"Serums","main_category_id":1,"main_category_name":"Face Care"}],"colors":[],"sizes":[{"id":1653,"name":"30 ml","price":55000,"qty":23,"sold":0,"color_id":null,"images":["1968.jpeg"]}],"images":[{"id":3241,"url":"1968.jpeg","color_id":null,"size_id":1653}]},{"id":27,"name":"La Roche Posay Hyalu B5 Serum","description":"سيروم الهيالورونيك أسيد وفيتامين B5 من لاروش \nمضاد للتجاعيد، وفقدان الحجم والمرونة، للعناية بالبشرة الضعيفة والمتعبة\n⁣\nيتعلق الأمر بوصفة فريدة لإعادة الحيوية للبشرة تمزج بين نوعين من حمض الهياليرونيك الخالص، وفيتامين B5، ومادة الماديكاسوزيد، لإعادة إشراق البشرة، وإصلاح حاجزها الجلدي، وبالتالي تحسين عملية تجديد ⁣خلايا البشرة\n⁣يحفز انتاج الكولاجين ويحافظ على رطوبة ومرونة البشرة من اول استعمال⁣","brand_id":70,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-24T14:08:42.412Z","updated_at":"2024-09-17T18:33:03.986Z","categories":[{"id":170,"name":"Serums","main_category_id":1,"main_category_name":"Face Care"}],"colors":[],"sizes":[{"id":31,"name":"30 ml","price":55000,"qty":32,"sold":0,"color_id":null,"images":["1074.jpeg"]}],"images":[{"id":3236,"url":"1074.jpeg","color_id":null,"size_id":31}]},{"id":28,"name":"La Roche Posay Retinol B3 Serum","description":"سيروم الريتنول من La roche \n-يعمل الريتنول على منع ظهور علامات التقدم بالسن حيث يعمل فيتامين  A على اختراق طبقات الجلد  ويعمل على تحفيز الجلد والكولاجين وبالتالي يقلل من ظهور التجاعيد والخطوط الدقيقه \n-يعمل الريتنول على البقع الداكنه حيث يعمل على تقليل التصبغات والبقع الداكنه وبذلك يعمل على توحيد لون البشره \n-يعمل على ترطيب الجلد ويقلل من تهيج البشره ويقلل من ظهور حب الشباب وكذلك يعمل على زيادة اشراقه البشره","brand_id":70,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-24T14:11:37.469Z","updated_at":"2024-09-23T15:51:16.057Z","categories":[{"id":170,"name":"Serums","main_category_id":1,"main_category_name":"Face Care"}],"colors":[],"sizes":[{"id":1652,"name":"30 ml","price":55000,"qty":1,"sold":0,"color_id":null,"images":["1967.jpeg"]}],"images":[{"id":21,"url":"1967.jpeg","color_id":null,"size_id":1652}]},{"id":31,"name":"La Roche Posay Nutritic Lips","description":"مرطب الشفاه من لاروش \n-مرطب للشفاه حيث يمتاز بفعاليته الكبرى على ترطيب الشفاه وتخليصها من الجفاف والتشققات\n-يوفر مرطب الشفاه التغذيه اللازمه من الفيتامينات والعناصر اللازمه\n-يعطي شفاه جميله ورطبة ومحميه لمده ٢٤ساعه","brand_id":70,"has_color":false,"has_size":true,"product_type":"size","price":0,"qty":0,"sold":0,"created_at":"2024-08-24T15:45:00.777Z","updated_at":"2024-09-17T18:44:29.075Z","categories":[{"id":153,"name":"Lip Balm","main_category_id":5,"main_category_name":"Lip Care"}],"colors":[],"sizes":[{"id":585,"name":"4.7","price":15000,"qty":3,"sold":0,"color_id":null,"images":["1084.jpeg"]}],"images":[{"id":3243,"url":"1084.jpeg","color_id":null,"size_id":585}]}],"total":808,"page":1,"itemsPerPage":15,"totalPages":54,"hasMore":true,"minPrice":0,"maxPrice":250000}