<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);

$db = $GLOBALS['db'];
global $app_list_strings;


if (isset($_GET['date_from'])) {
    $dateFrom = date("Y-m-d", strtotime($_GET['date_from']));
} else {
    $dateFrom = date("Y-m-d");
}

if (isset($_GET['date_to'])) {
    if (strlen($_GET['date_to']) > 0) {
        $dateTo = date("Y-m-d", strtotime($_GET['date_to']));
    }
} else {
    $dateTo = date("Y-m-d", strtotime("+ 1 month"));
}

if (!isset($_GET['hideReadyProducts'])) {
    $_GET['hideReadyProducts'] = "false";
}

if (!isset($_GET['ajaxAction'])) {
    $allQuery = "SELECT s.id, s.document_no, s.status, s.parent_name, s.parent_id, s.send_date, s.type,
                     s.register_date, s.delivery_date, si.code, si.name, si.ecmproduct_id, si.description,
                     si.quantity, p.vendor_part_no as kind, p.brand, p.part_no as size, p.shape,
                     ss.quantity as stockState, si.id as item_id, s.shipping_address_name, si.production_date,
                     COUNT(ps.id) AS scheduled
                FROM ecmsaleitems AS si
                INNER JOIN ecmsales AS s
                ON s.id = si.ecmsale_id
                INNER JOIN ecmproducts AS p
                ON si.ecmproduct_id = p.id
                LEFT JOIN ecmstockstates AS ss
                ON ss.product_id = si.ecmproduct_id AND ss.stock_id = 'c7afd71a-4c3a-bde4-138d-4acaee1644e4'
                LEFT JOIN productionScheduler AS ps
                ON si.id = ps.ecmsaleitem_id AND ps.deleted=0
                WHERE s.delivery_date > '$dateFrom'";
    if (is_array($_GET['exclude']) && count($_GET['exclude']) > 0) {
        foreach ($_GET['exclude'] as $name) {
            if (strlen($name) > 0) {
                $allQuery .= " AND s.parent_name NOT LIKE '%$name%'";
            }
        }
    }

    if (is_array($_GET['excludeType']) && count($_GET['excludeType']) > 0) {
        foreach ($_GET['excludeType'] as $type) {
            if (strlen($type) > 0) {
                if ($type == 'other') {
                    $allQuery .= " AND s.type NOT IN ('b2b', 'interval_order')";
                } else {
                    $allQuery .= " AND s.type != '$type'";
                }
            }
        }
    }

    $typesWhere = "";
    if (strlen($dateTo) > 0) {
        $allQuery .= " AND s.delivery_date < '$dateTo'";
        $typesWhere = " AND s.delivery_date < '$dateTo'";
    } else {
        $allQuery .= " OR s.delivery_date IS NULL";
        $typesWhere = " OR s.delivery_date IS NULL";
    }
    $allQuery .= "GROUP BY si.id ORDER BY s.delivery_date, s.register_date, s.document_no";

    $rows = $db->query($allQuery);
    $allData = array();
    $i = 0;
    while ($r = $db->fetchByAssoc($rows)) {
        $row = array();
        $i++;
        $row['position'] = $i;
        $row['productName'] = strlen($r['name']) > 55 ? substr($r['name'], 0, 55) . "..." : $r['name'];
        $row['productFullName'] = $r['name'];
        $row['productCode'] = strlen($r['code']) > 20 ? substr($r['code'], 0, 20) . "..." : $r['code'];
        $row['productFullCode'] = $r['code'];
        $row['productId'] = $r['ecmproduct_id'];
        $row['productQty'] = $r['quantity'];
        $row['productKind'] = $r['kind'];
        $row['productSize'] = $r['size'];
        $row['productShape'] = $app_list_strings['ecmproducts_shape_dom'][$r['shape']];
        $row['productBrand'] = $app_list_strings['ecmproducts_brand_dom'][$r['brand']];
        $row['orderNo'] = $r['document_no'];
        $row['orderId'] = $r['id'];
        $row['orderStatus'] = $app_list_strings['ecmsales_status_dom'][$r['status']];
        $row['orderType'] = $app_list_strings['ecmsales_type_dom'][$r['type']];
        $row['orderParent'] = $r['parent_name'];
        $row['orderParentId'] = $r['parent_id'];
        $row['orderRegisterDate'] = $r['register_date'];
        $row['orderDeliveryDate'] = $r['delivery_date'];
        $row['orderSendDate'] = $r['send_date'];
        $row['orderItemId'] = $r['item_id'];
        $row['description'] = strlen($r['description']) > 0 ? substr($r['description'], 0, 30) : '';
        $row['fullDescription'] = $r['description'];
        $row['shippingTo'] = ($r['shipping_address_name'] == 'Adres korespondencyjny' ? '' : $r['shipping_address_name']);
        $row['productionDate'] = $r['production_date'];
        $row['productStockState'] = $r['stockState'] | 0;
        $row['scheduled'] = $r['scheduled'];

        if ($_GET['hideReadyProducts'] == "false" || $row['productQty'] > $row['productStockState']) {
            $allData[] = $row;
        }
    }

    $orderTypes = [];
    $res  = $db->query("SELECT distinct s.type FROM ecmsales AS s WHERE s.delivery_date > '$dateFrom' $typesWhere");
    while ($r = $db->fetchByAssoc($res)) {
        $orderTypes[] = $r['type'];
    }
    $types = [];
    foreach ($app_list_strings['ecmsales_type_dom'] as $key => $value) {
        if (in_array($key, $orderTypes)) {
            $types[$key] = $value;
        }
    }

    $smarty = new Sugar_Smarty();
    $smarty->assign("exclude", $_GET['exclude']);
    $smarty->assign("excludeType", $_GET['excludeType']);
    $smarty->assign("allData", $allData);
    $smarty->assign("dateFrom", $GLOBALS['timedate']->to_display_date($dateFrom));
    $smarty->assign("dateTo", $GLOBALS['timedate']->to_display_date($dateTo));
    $smarty->assign("types", $types);
    $smarty->assign("hideReadyProducts", $_GET['hideReadyProducts']);

    echo $smarty->display('modules/EcmReports/BimIT-Reports/productsBySales/productsBySales.tpl');
} else {
    switch ($_GET['ajaxAction']) {
        case 'getComponents':
            echo getComponents($_POST['ids'], $dateFrom, $dateTo);
            break;
        case 'getRawMaterials':
            echo getRawMaterials($_POST['ids'], $_POST['cids']);
            break;
        case 'saveProductDescription':
            saveProductDescription($_GET['itemId'], $_GET['description']);
            break;
        case 'addToProductionScheduler':
            addToProductionScheduler($_GET['itemId']);
            break;
        case 'addComponentToProductionScheduler':
            addComponentToProductionScheduler($_GET['productId'], $_GET['qty']);
            break;
    }
}

// helpers
function findProduct($array, $value)
{
    for ($i = 0; $i < count($array); $i++) {
        if ($array[$i]['productId'] == $value) {
            return $i;
        }
    }
    return -1;
}

function getComponents($ids, $dateFrom, $dateTo)
{
    $db = $GLOBALS['db'];
    global $app_list_strings;
    $idsString = join("','", $ids);
    $productsQuery = "SELECT si.ecmproduct_id, SUM(si.quantity) as quantity
                        FROM ecmsaleitems AS si
                        INNER JOIN ecmsales AS s
                        ON s.id = si.ecmsale_id
                        WHERE si.id IN ('" . $idsString . "')
                        GROUP BY si.ecmproduct_id";
    $rows = $db->query($productsQuery);
    $componentsData = array();
    while ($r = $db->fetchByAssoc($rows)) {
        $componentsQuery = "SELECT p.code, p.name, c.quantity, p.unit_id, c.ecmcomponent_id, ss.quantity as stockState, 
                                p.group_ks, COUNT(ps.id) AS scheduled 
                                FROM ecmproductcomponents as c
                                INNER JOIN ecmproducts AS p
                                ON p.id = c.ecmcomponent_id
                                LEFT JOIN ecmstockstates AS ss
                                ON ss.product_id = p.id AND ss.stock_id = '368479db-22c5-0220-3a14-4bc426b1c709'
                                LEFT JOIN productionScheduler AS ps
                                ON p.id = ps.ecmproduct_id AND ps.is_component = 1 AND ps.deleted=0
                                WHERE c.ecmproduct_id = '" . $r['ecmproduct_id'] . "' GROUP BY p.id";
        $crows = $db->query($componentsQuery);
        while ($cr = $db->fetchByAssoc($crows)) {
            $exists = findProduct($componentsData, $cr['ecmcomponent_id']);
            if ($exists > -1) {
                $componentsData[$exists]['productQty'] += $r['quantity'] * $cr['quantity'];
            } else {
                $ordered = $db->fetchByAssoc($db->query("SELECT SUM(poi.quantity) as ordered, GROUP_CONCAT(poi.ecmpurchaseorder_id SEPARATOR '|') AS orders
                                                            FROM ecmpurchaseorderitems as poi
                                                            INNER JOIN ecmpurchaseorders as po
                                                            ON poi.ecmpurchaseorder_id = po.id AND (po.status='registered' OR po.status='accepted') AND po.deleted=0
                                                            WHERE poi.deleted=0 AND poi.ecmproduct_id = '" . $cr['ecmcomponent_id'] . "'"));
                $orders = array();
                $ordersIds = explode('|', $ordered['orders']);
                $ordersRes = $db->query("SELECT id, document_no, delivery_date FROM ecmpurchaseorders WHERE id IN ('" . join("','", $ordersIds) . "') ORDER BY date_entered DESC");
                while ($o = $db->fetchByAssoc($ordersRes)) {
                    $orders[] = array(
                        'orderId' => $o['id'],
                        'orderNr' => $o['document_no'],
                        'orderDeliveryDate' => isset($o['delivery_date']) ? explode(' ', $o['delivery_date'])[0] : ''
                    );
                }
                $vendor = $db->fetchByAssoc($db->query("SELECT d.parent_id, a.name
                                                            FROM ecmstockdocinitems AS i
                                                            INNER JOIN ecmstockdocins AS d
                                                            ON d.id = i.ecmstockdocin_id
                                                            INNER JOIN accounts AS a
                                                            ON a.id = d.parent_id
                                                            WHERE i.ecmproduct_id = '" . $cr['ecmcomponent_id'] . "'
                                                            ORDER BY d.register_date DESC 
                                                            LIMIT 0,1"));

                $row = array();
                $row['productId'] = $cr['ecmcomponent_id'];
                $row['productName'] = strlen($cr['name']) > 55 ? substr($cr['name'], 0, 55) . "..." : $cr['name'];
                $row['productFullName'] = $cr['name'];
                $row['productCode'] = strlen($cr['code']) > 20 ? substr($cr['code'], 0, 20) . "..." : $cr['code'];
                $row['productFullCode'] = $cr['code'];
                $row['productUnit'] = $app_list_strings['ecmproducts_unit_dom'][$cr['unit_id']];
                $row['productOrdered'] = (!empty($ordered['ordered'])) ? $ordered['ordered'] : 0;
                $row['productVendorName'] = $vendor ? $vendor['name'] : '';
                $row['productVendorId'] = $vendor ? $vendor['parent_id'] : '';
                $row['productQty'] = $r['quantity'] * $cr['quantity'];
                $row['productGroupKS'] = $cr['group_ks'];
                $row['orders'] = $orders;
                $row['productStockState'] = (!empty($cr['stockState'])) ? $cr['stockState'] : 0;
                $row['scheduled'] = $cr['scheduled'];
                $componentsData[] = $row;
            }
        }
    }
    echo json_encode($componentsData);
}

function getRawMaterials($ids, $cids)
{
    $db = $GLOBALS['db'];
    global $app_list_strings;
    $idsString = join("','", $ids);
    $cidsString = join("','", $cids);
    $productsQuery = "SELECT si.ecmproduct_id, SUM(si.quantity) as quantity
                        FROM ecmsaleitems AS si
                        INNER JOIN ecmsales AS s
                        ON s.id = si.ecmsale_id
                        WHERE si.id IN ('$idsString')
                        GROUP BY si.ecmproduct_id";
    $prows = $db->query($productsQuery);
    $rawMaterialsData = array();
    while ($p = $db->fetchByAssoc($prows)) {
        $componentsQuery = "SELECT c.ecmcomponent_id, c.quantity
        FROM ecmproductcomponents as c
        WHERE c.ecmproduct_id = '" . $p['ecmproduct_id'] . "' AND c.ecmcomponent_id IN ('$cidsString')";
        $crows = $db->query($componentsQuery);
        while ($c = $db->fetchByAssoc($crows)) {
            // szukamy komponentów wdal
            $componentRawMaterials = getProductRawMaterials($c['ecmcomponent_id'], $c['quantity']);
            foreach ($componentRawMaterials as $material) {
                $product = $db->fetchByAssoc($db->query("
                    SELECT p.id, p.code, p.name, p.group_ks, p.unit_id, ss.quantity as stockState
                    FROM ecmproducts AS p
                    LEFT JOIN ecmstockstates AS ss
                    ON ss.product_id = p.id AND ss.stock_id = '368479db-22c5-0220-3a14-4bc426b1c709'
                    WHERE p.id='" . $material['ecmproduct_id'] . "'
                "));
                $ordered = $db->fetchByAssoc($db->query("SELECT SUM(poi.quantity) as ordered,  GROUP_CONCAT(poi.ecmpurchaseorder_id SEPARATOR '|') AS orders
                    FROM ecmpurchaseorderitems as poi
                    INNER JOIN ecmpurchaseorders as po
                    ON poi.ecmpurchaseorder_id = po.id AND (po.status='registered' OR po.status='accepted') AND po.deleted=0
                    WHERE poi.deleted=0 AND poi.ecmproduct_id = '" . $material['ecmproduct_id'] . "'"));
                $orders = array();
                $ordersIds = explode('|', $ordered['orders']);
                $ordersRes = $db->query("SELECT id, document_no, delivery_date FROM ecmpurchaseorders WHERE id IN ('" . join("','", $ordersIds) . "') ORDER BY date_entered DESC");
                while ($o = $db->fetchByAssoc($ordersRes)) {
                    $orders[] = array(
                        'orderId' => $o['id'],
                        'orderNr' => $o['document_no'],
                        'orderDeliveryDate' => isset($o['delivery_date']) ? explode(' ', $o['delivery_date'])[0] : ''
                    );
                }
                $vendor = $db->fetchByAssoc($db->query("SELECT d.parent_id, a.name
                    FROM ecmstockdocinitems AS i
                    INNER JOIN ecmstockdocins AS d
                    ON d.id = i.ecmstockdocin_id
                    INNER JOIN accounts AS a
                    ON a.id = d.parent_id
                    WHERE i.ecmproduct_id = '" . $material['ecmproduct_id'] . "'
                    ORDER BY d.register_date DESC 
                    LIMIT 0,1"));
                $row = array();
                $row['productId'] = $product['id'];
                $row['productName'] = strlen($product['name']) > 55 ? substr($product['name'], 0, 55) . "..." : $product['name'];
                $row['productFullName'] = $product['name'];
                $row['productCode'] = strlen($product['code']) > 20 ? substr($product['code'], 0, 20) . "..." : $product['code'];
                $row['productFullCode'] = $product['code'];
                $row['productUnit'] = $app_list_strings['ecmproducts_unit_dom'][$product['unit_id']];
                $row['productOrdered'] = (!empty($ordered['ordered'])) ? $ordered['ordered'] : 0;
                $row['productVendorName'] = $vendor ? $vendor['name'] : '';
                $row['productVendorId'] = $vendor ? $vendor['parent_id'] : '';
                $row['productQty'] = $p['quantity'] * $material['quantity'];
                $row['productGroupKS'] = $product['group_ks'];
                $row['orders'] = $orders;
                $row['productStockState'] = (!empty($product['stockState'])) ? $product['stockState'] : 0;
                $rawMaterialsData[] = $row;
            }
        }
    }
    
    // group rawMaterialsData by productId and sum quantity and ordered
    $tmp = array_reduce($rawMaterialsData, function ($carry, $item) {
        if (isset($carry[$item['productId']])) {
            $carry[$item['productId']]['productQty'] += $item['productQty'];
        } else {
            $carry[$item['productId']] = $item;
        }
        return $carry;
    }, array());
    // flat tmp array
    $rawMaterialsData = array_values($tmp);
    
    echo json_encode($rawMaterialsData);
}
function getProductRawMaterials($productId, $quantity)
{
    $db = $GLOBALS['db'];
    $response = array();
    $componentsQuery = "SELECT c.ecmcomponent_id, c.quantity
    FROM ecmproductcomponents as c
    WHERE c.ecmproduct_id = '$productId'";
    $crows = $db->query($componentsQuery);
    if ($crows->num_rows == 0) {
        return array(
            array(
                'ecmproduct_id' => $productId,
                'quantity' => $quantity
            )
        );
    } else {
        while ($c = $db->fetchByAssoc($crows)) {
            $response =  array_merge($response, getProductRawMaterials($c['ecmcomponent_id'], $quantity * $c['quantity']));
        }
        return $response;
    }
}

function addToProductionScheduler($orderItemId) {
    $db = $GLOBALS['db'];
    global $current_user;
    $res = $db->fetchByAssoc($db->query("SELECT quantity, ecmproduct_id, description, ecmsale_id FROM ecmsaleitems WHERE id ='$orderItemId'"));
    $query = sprintf("INSERT INTO productionScheduler VALUES ('%s', '%s', '%s', '%d', NOW(), NOW(), '%s', '%s', 0, '%s', 0, '','%s');",
        generateUuidV4(), $orderItemId, $res['ecmsale_id'], $res['quantity'], $current_user->id, $current_user->id, $res['ecmproduct_id'], $res['description']);
    $db->query($query);
}

function addComponentToProductionScheduler($productId, $qty) {
    $db = $GLOBALS['db'];
    global $current_user;
    $query = sprintf("INSERT INTO productionScheduler VALUES ('%s', null, null, '%d', NOW(), NOW(), '%s', '%s', 0, '%s', 1, null, null);",
        generateUuidV4(), $qty, $current_user->id, $current_user->id, $productId);
    $db->query($query);
}

function generateUuidV4() {
    $data = openssl_random_pseudo_bytes(16);
    $data[6] = chr(ord($data[6]) & 0x0f | 0x40);
    $data[8] = chr(ord($data[8]) & 0x3f | 0x80);
    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
