<?php

namespace App\ExactApi;

use App\ExactApi\Product;
use Doctrine\DBAL\Connection;

class IsotopeDatabaseHandler
{
    private $connection;

    public function __construct(Connection $connection)
    {
        $this->connection = $connection;
    }

    public function processProducts(array $products)
    {
        $this->connection->beginTransaction();

        $sql = "SELECT * FROM `tl_iso_product`";
        $stmt = $this->connection->query($sql);
        $dbProducts = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $sql = "SELECT * FROM `tl_iso_product_price`";
        $stmt = $this->connection->query($sql);
        $dbProductPrices = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $dbProductsBySku = [];
        foreach ($dbProducts as $prod) {
            $dbProductsBySku[$prod['sku']] = $prod;
        }

        $dbProductsPricesByPid = [];
        foreach ($dbProductPrices as $price) {
            $dbProductsPricesByPid[$price['pid']] = $price;
        }

        /** @var Product $product */
        foreach ($products as $product) {

            if (array_key_exists($product->getCode(), $dbProductsBySku)) {
                $dbProduct = $dbProductsBySku[$product->getCode()];
                $dbPrice = $dbProductsPricesByPid[$dbProduct['id']];
                $this->updateProduct($product, $dbProduct['id']);
                $this->updatePriceTier($product, $dbPrice['id']);

            } else {
                $productId = $this->createProduct($product);
                $productPriceId = $this->createPrice($product, $productId);
                $this->createPriceTier($product, $productPriceId);
            }
        }
        $this->connection->commit();
    }

    private function updateProduct(Product $product, $productDbId)
    {
        $shippingWeight = $this->convertShippingWeight($product);
        $sql =
            "UPDATE `tl_iso_product` SET
                tstamp = ".time().",
                shipping_weight = '$shippingWeight'
             WHERE `id` = ".$productDbId;
        $this->connection->query($sql);
    }

    private function updatePriceTier(Product $product, $priceDbId)
    {
        $price = $product->getStandardSalesPrice() * (1 + Product::VAT);
        $sql =
            "UPDATE `tl_iso_product_pricetier` SET
                tstamp = ".time().",
                price = $price
             WHERE `pid` = ".$priceDbId;
        $this->connection->query($sql);
    }

    private function createProduct(Product $product)
    {
        $alias = 'exact-product-'.$product->getCode();
        $shippingWeight = $this->convertShippingWeight($product);
        $sql =
            "INSERT into `tl_iso_product` (
                pid,
                gid,
                tstamp,
                language,
                dateAdded,
                type,
                fallback,
                alias,
                gtin,
                sku,
                name,
                description,
                meta_title,
                baseprice,
                shipping_weight,
                shipping_exempt,
                shipping_pickup,
                shipping_price,
                protected,
                guests,
                cssID,
                published,
                start,
                stop,
                exact_id              
             ) VALUES (
                0,
                0,
                ".time().",
                '',
                ".time().",
                2,
                '',
                '$alias',
                '',
                '".$product->getCode()."',
                '".$product->getDescription()."',
                '".$product->getExtraDescription()."',
                '',
                '',
                '$shippingWeight',
                '',
                '',
                0.00,
                '',
                '',
                '',
                '0',
                '',
                '',
                '".$product->getId()."'
             )";
        $this->connection->query($sql);
        return $this->connection->lastInsertId();
    }

    private function createPrice(Product $product, $productDbId)
    {
        $sql =
            "INSERT INTO `tl_iso_product_price` (
                pid,
                tstamp,
                tax_class,
                config_id,
                member_group,
                start,
                stop
            ) VALUES (
                $productDbId,
                ".time().",
                1,
                0,
                0,
                '',
                ''
            )";
        $this->connection->query($sql);
        return $this->connection->lastInsertId();
    }

    private function createPriceTier(Product $product, $productPriceDbId)
    {
        $price = $product->getStandardSalesPrice() * (1 + Product::VAT);
        $sql =
            "INSERT INTO `tl_iso_product_pricetier` (
                pid,
                tstamp,
                min,
                price
            ) VALUES (
                $productPriceDbId,
                ".time().",
                1,
                $price
            )";
        $this->connection->query($sql);
        return $this->connection->lastInsertId();
    }

    private function convertShippingWeight(Product $product)
    {
        $shippingWeight = $product->getGrossWeight() !== '' ?
            $product->getGrossWeight() :
            $product->getNetWeight();
        return ((int) $shippingWeight === 0 || $shippingWeight === '') ?
            '' :
            'a:2:{s:4:"unit";s:2:"kg";s:5:"value";s:3:"' . $shippingWeight . '";}';
    }
}