<?php

class SuppliersProducts {
    private $headersHelper;

    function __construct(){
        $this->headersHelper =  new HeadersHelper();
    }

    /**
     * add new product
     * @param HashArray $productData product data input
     * @return Array insert message
     */
    public function addSupplierProduct($productData){
        global $database;

        foreach ($productData as $key => $value) {
            $productData[$key] = $database->escapeValue($value);
        }

        if(intval($productData['isPriceRecurring']) === 0){
            $productData['payPeriod'] = 0;
        }

        $data = $this->validateProductData($productData, 'add');

        if(!empty($data)){
            return $data;
        }

        $sql = "INSERT INTO ".TABLES['suppliers_countries_products']."
                (idCountry, idSupplier, idProductCategory, unitCostPrice, unitVatCost, productName, productDescription, manufacturerProductNo, supplierProductNo, unit, isPriceRecurring, payPeriod)
                VALUES('".$productData['idCountry']."',
                '".$productData['idSupplier']."',
                '".$productData['idProductCategory']."',
                '".$productData['unitCostPrice']."',
                '".$productData['unitVatCost']."',
                '".$productData['name']."',
                '".$productData['description']."',
                '".$productData['manufacturerProductNo']."',
                '".$productData['supplierProductNo']."',
                '".$productData['unit']."',
                '".$productData['isPriceRecurring']."',
                '".$productData['payPeriod']."'
                )";
        $query = $database->query($sql);

        if($database->affectedRows() !== 1){
            $data['messages'][] =[
                'code' => 'error',
                'message' => 'SERVER_ERROR'
            ];

            return $data;
        }

        $data['messages'][] = [
            'code' => 'success',
            'message' => 'SUPPLIER_PRODCT_ADDED'
        ];

        return $data;
    }

    public function updatePackageAvailability($idProduct = 0, $idPackage =0){
        global $database;

        $whereSql = " 1=1 ";
        if($idProduct !== 0){
            $whereSql .= " AND idProduct=$idProduct";
        }

        if($idPackage !== 0){
            $whereSql .= " AND idPackage=$idPackage";
        }
        $sql = "UPDATE packages p
                INNER JOIN
                (
                	SELECT rpp.idPackage,
                		SUM(scp.isAvailable) AS availableProducts,
                        count(scp.idProduct) as totalProducts
                	FROM ".TABLES['suppliers_countries_products']." scp
                	INNER JOIN ".TABLES['rel_package_products']." rpp
                	ON rpp.idProduct=scp.idProduct
                	INNER JOIN
                	(
                		SELECT idPackage, max(packageInstance) AS packageInstance
                		FROM ".TABLES['rel_package_products']."
                        WHERE $whereSql
                		GROUP BY idPackage
                	) maxInst
                	ON maxInst.idPackage=rpp.idPackage AND maxInst.packageInstance=rpp.packageInstance
                	GROUP BY rpp.idPackage
                ) newStatus
                ON newStatus.idPackage=p.id
                SET p.status=CASE WHEN availableProducts=totalProducts THEN 'available' ELSE 'not-available' END";
        $query = $database->query($sql);

        return $database->affectedRows() > 0;
    }

    /**
     * edit product data
     * @param  HashArray $productData product data input
     * @return Array             update message
     */
    public function editSupplierProduct($productData){
        global $database;
        $prices = new Prices();

        foreach ($productData as $key => $value) {
            $productData[$key] = $database->escapeValue($value);
        }

        if(intval($productData['isPriceRecurring']) === 0){
            $productData['payPeriod'] = 0;
        }

        $data = $this->validateProductData($productData, 'edit');

        if(!empty($data)){
            return $data;
        }

        $sql = "UPDATE ".TABLES['suppliers_countries_products']."
                SET unitCostPrice='".$productData['unitCostPrice']."',
                unitVatCost='".$productData['unitVatCost']."',
                productName='".$productData['name']."',
                productDescription='".$productData['description']."',
                manufacturerProductNo='".$productData['manufacturerProductNo']."',
                supplierProductNo='".$productData['supplierProductNo']."',
                unit='".$productData['unit']."',
                idProductCategory='".$productData['idProductCategory']."',
                isPriceRecurring='".$productData['isPriceRecurring']."',
                payPeriod='".$productData['payPeriod']."',
                isAvailable=".$productData['isAvailable']."
                WHERE idProduct='".$productData['idProduct']."'
                LIMIT 1";
        $query = $database->query($sql);

        if($database->affectedRows() !== 1){
            $data['messages'][] = [
                'code' => 'warning',
                'message' => 'NO_CHANGES'
            ];

            return $data;
        }

        $packageUpdate = $this->updatePackageAvailability($productData['idProduct']);
        if($packageUpdate > 0){
            $data['messages'][] = [
                'code' => 'warning',
                'message' => 'PACKAGES_AVAILABLITY_CHANGED'
            ];
        }

        $priceChange = $prices->checkPackagePriceMargin($productData['idProduct'], 0);
        if($priceChange > 0){
            $data['messages'][] = [
                'code' => 'warning',
                'message' => 'PACKAGES_HIGH_PRICE_CHANGED'
            ];
        }

        $data['messages'][] = [
            'code' => 'success',
            'message' => 'SUPPLIER_PRODUCT_EDITED'
        ];

        return $data;
    }

    /**
     * @return Array id and name of the available product categories
     */
    public function getProductCategories() {
        global $database;

        $sql = "SELECT
                  id,
                  category
                FROM ".TABLES['product_categories']."
                ORDER BY category";

        return $database->fetchResultArray($sql);
    }


    /**
     * check if product data is valid
     * @param  HashArray $productData product data input
     * @return Array               empty array if valid or error message array
     */
    private function validateProductData($productData, $action){
        global $database;
        $data = [];

        $whereSql = $action === 'edit' ? ' AND idProduct!='.$productData['idProduct'] : '';
        $sql = "SELECT idProduct
                FROM ".TABLES['suppliers_countries_products']."
                WHERE productName='".$productData['name']."' AND idCountry=".$productData['idCountry']." AND idSupplier=".$productData['idSupplier']." $whereSql
                LIMIT 1";
        $query = $database->query($sql);
        if($database->numRows($query) !== 0){
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'DUPLICATE_ENTRY'
            ];

            return $data;
        }

        if(!$productData['idCountry'] ){
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'SELECT_COUNTRY'
            ];

            return $data;
        }

        if(!$productData['idSupplier']){
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'SELECT_SUPPLIER'
            ];

            return $data;
        }

        if($action === 'edit' && (intval($productData['isAvailable']) !== 1 && intval($productData['isAvailable']) !== 0)){
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'INVALID_VALUE_IS_AVAILABLE'
            ];

            return $data;
        }

        if(!$productData['idProductCategory']){
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'SELECT_CATEGORY'
            ];

            return $data;
        }

        $checkMessage = $database->isEmpty('name', $productData['name']);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }
        $checkMessage = $database->invalidLength('name', $productData['name'], 70);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }
        $checkMessage = $database->isEmpty('description', $productData['description']);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }
        $checkMessage = $database->invalidLength('description', $productData['description'], 500);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }
        $checkMessage = $database->isEmpty('unitCostPrice', $productData['unitCostPrice']);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }
        $checkMessage = $database->invalidNumber('unitCostPrice', $productData['unitCostPrice'], 0, 10000000000);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }
        $checkMessage = $database->isEmpty('unitVatCost', $productData['unitVatCost']);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }
        $checkMessage = $database->invalidNumber('unitVatCost', $productData['unitVatCost'], 0, 10000000000);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }
        $checkMessage = $database->isEmpty('manufacturerProductNo', $productData['manufacturerProductNo']);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }
        $checkMessage = $database->invalidLength('manufacturerProductNo', $productData['manufacturerProductNo'], 45);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }
        $checkMessage = $database->isEmpty('supplierProductNo', $productData['supplierProductNo']);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }
        $checkMessage = $database->invalidLength('supplierProductNo', $productData['supplierProductNo'], 45);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }

        $checkMessage = $database->isEmpty('isPriceRecurring', $productData['isPriceRecurring']);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }

        if($productData['isPriceRecurring'] !== '1' && $productData['isPriceRecurring'] !== '0'){
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'INVALID_VALUE_RECURRING'
            ];
        }

        if($productData['isPriceRecurring'] === '1'){
            $checkMessage = $database->isEmpty('payPeriod', $productData['payPeriod']);
            if($checkMessage){
                $data['messages'][] = $checkMessage;
            }

            $checkMessage = $database->invalidNumber('payPeriod', $productData['payPeriod'], 0, 36);
            if($checkMessage){
                $data['messages'][] = $checkMessage;
            }
        }

        return $data;
    }

    /**
     * get produts documents
     * @param  INT $idProduct   id for product, if 0 all values are retrieved
     * @return Array            list of documents grouped by product id
     */
    private function getSupplierProductsDocuments($idProduct = 0){
        global $database;
        $idProduct = $database->escapeValue($idProduct);
        $data = [];
        $whereSql = "";

        if($idProduct){
            $whereSql = "WHERE rpd.idProduct=$idProduct";
        }

        $sql = "SELECT
                   d.id AS idDocument,
                   d.documentName,
                   d.documentPath,
                   dt.type AS documentType,
                   d.extension,
                   rpd.idProduct
               FROM ".TABLES['documents']." d
               INNER JOIN ".TABLES['document_types']." dt
                   ON dt.id=d.idDocumentType
               INNER JOIN ".TABLES['rel_product_documents']." rpd
                   ON rpd.idDocument=d.id
                $whereSql";
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)){
            $data[$row['idProduct']][] = $row;
        }

        return $data;
    }

    /**
     * get the list with all products for a country
     * @param  integer $country id of the country to get the products
     * @return Array array with all productus for the suppiers in a specific country
     */
    public function getSuppliersProducts($idCountry = 0, $idProduct = 0){
        global $database;
        $whereSql = " WHERE 1=1";
        $data = [];

        if($idCountry != 0){
            $whereSql .= " AND c.id=$idCountry ";
        }

        if($idProduct != 0){
            $whereSql .= " AND scp.idProduct=$idProduct ";
        }

        $headersSql = $this->getSuppliersProductsHeaders('sql');
        $productsDocuments =$this->getSupplierProductsDocuments($idProduct);

        $sql = "SELECT  $headersSql
                FROM ".TABLES['suppliers_countries_products']." scp
                INNER JOIN ".TABLES['suppliers']." s
                    ON s.id=scp.idSupplier
                INNER JOIN ".TABLES['countries']." c
                    ON c.id=scp.idCountry
                INNER JOIN ".TABLES['product_categories']." pc
                    ON pc.id=scp.idProductCategory
                $whereSql
                ORDER BY c.name, scp.productName, s.name ASC";

        $query = $database->query($sql);
        while($row = $database->fetchArray($query)){
            $row['documents'] = isset($productsDocuments[$row['idProduct']]) ? $productsDocuments[$row['idProduct']] : [];
            $data[] = $row;
        }
        return $data;
    }


    /**
     * Get the headers requried for products for the suppliers
     * @param  string $type type of the header, posible values array or sql
     * @return string|array      returns the sql header or the array of for the headers
     */
    public function getSuppliersProductsHeaders($type = 'array'){
        $headers = [
            'scp.idProduct' => 'idProduct',
            'scp.idSupplier' => 'idSupplier',
            'pc.idType' => 'idProductType',
            'pc.category' => 'category',
            'scp.productName' => 'name',
            'scp.productDescription' => 'description',
            'scp.manufacturerProductNo' => 'manufacturerProductNo',
            'scp.supplierProductNo' => 'supplierProductNo',
            'scp.unit' => 'unit',
            'scp.idCountry' => 'idCountry',
            'scp.isPriceRecurring' => 'isPriceRecurring',
            'scp.payPeriod' => 'payPeriod',
            'scp.unitCostPrice' => 'unitCostPrice',
            'scp.unitVatCost' => 'unitVatCost',
            'scp.isAvailable' => 'isAvailable',
            's.name' => 'supplierName',
            'c.name' => 'country',
            '\'\'' => 'documents'
        ];

        return $this->headersHelper->getHeader($headers, $type);
    }

    /**
     * upload document for a product
     * @param  INT $idDocumentType     id for document type
     * @param  INT $idSupplierProduct id for product
     * @param  String $documentName    name for the document
     * @param  INT $visibleToCustomer  document will be visible for customer
     * @param  FILE $file              file to be uploaded
     * @return ARRAY                  upload message
     */
    public function uploadProductDocument($idDocumentType, $idSupplierProduct, $documentName, $visibleToCustomer, $file){
        global $database;

        if(!$idDocumentType){
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'NO_DOC_TYPE'
            ];

            return $data;
        }

        if($visibleToCustomer != 0 && $visibleToCustomer != 1){
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'WRONG_VISIBLE_TO_CUST_VAL'
            ];

            return $data;
        }

        if(!$documentName){
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'NO_NAME'
            ];

            return $data;
        }

        $fileManager = new FileManager();
        $data = $fileManager->uploadFile($file, $idDocumentType, $documentName, 0, 0, $visibleToCustomer);

        if(isset($data['messages'])){
            return $data;
        }

        $idDocument = $data['idDocument'];

        $sql = "INSERT INTO ".TABLES['rel_product_documents']."
                (idProduct, idDocument)
                VALUES($idSupplierProduct, $idDocument)";
        $query = $database->query($sql);

        $data['messages'][] = [
            'code' => 'success',
            'message' => 'DOCUMENT_UPLOADED'
        ];

        return $data;
    }

    /**
     * remove product documents
     * @param  INT $idDocument  id for document
     * @return Array            update message
     */
    public function removeProductDocument($idDocument){
        global $database, $user;

        if($user->getUserType() !== USER_TYPES['BROKER']){
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'NO_RIGHTS'
            ];

            return $data;
        }

        $fileManager = new FileManager();
        $data = $fileManager->removeDocument($idDocument);

       return $data;
    }

}
