<?php
namespace front\factory;

class ShopProduct
{
  // get_sellasist_product_id
  static public function get_sellasist_product_id( $product_id ) {
    global $mdb;
    if ( !$sellasist_product_id = $mdb -> get( 'pp_shop_products', 'sellasist_product_id', [ 'id' => $product_id ] ) ) {
      $sellasist_product_id = $mdb -> get( 'pp_shop_products', 'sellasist_product_id', [ 'id' =>
        $mdb -> get( 'pp_shop_products', 'parent_id', [ 'id' => $product_id ] )
      ] );
    }
    return $sellasist_product_id;
  }

  // get_product_sku
  static public function get_product_sku( $product_id )
  {
    global $mdb;
    return $mdb -> get( 'pp_shop_products', 'sku', [ 'id' => $product_id ] );
  }

  // get_product_ean
  static public function get_product_ean( $product_id )
  {
    global $mdb;
    return $mdb -> get( 'pp_shop_products', 'ean', [ 'id' => $product_id ] );
  }

  static public function is_product_active( int $product_id )
  {
    global $mdb;

    $cacheHandler = new \CacheHandler();
    $cacheKey = "\front\factory\ShopProduct::is_product_active:$product_id";

    $objectData = $cacheHandler -> get( $cacheKey );

    if ( !$objectData )
    {
      $is_active = $mdb -> get( 'pp_shop_products', 'status', [ 'id' => $product_id ] );

      $cacheHandler -> set( $cacheKey, $is_active );
    }
    else
    {
      return unserialize( $objectData );
    }
    return $is_active;
  }

  static public function product_url( $product )
  {
    if ( $product['language']['seo_link'] )
    {
      $url = '/' . $product['language']['seo_link'];
    }
    else
    {
      if ( $product['parent_id'] )
        $url = '/p-' . $product['parent_id'] . '-' . \S::seo( $product['language']['name'] );
      else
        $url = '/p-' . $product['id'] . '-' . \S::seo( $product['language']['name'] );
    }
    return $url;
  }

  static public function get_minimal_price( $id_product, $price_brutto_promo = null )
  {
    global $mdb;

    if ( !$price = \Cache::fetch( 'get_minimal_price:' . $id_product ) )
    {
      $price = $mdb -> min( 'pp_shop_product_price_history', 'price', [ 'AND' => [ 'id_product' => $id_product, 'price[!]' => str_replace( ',', '.', $price_brutto_promo ) ] ] );
      \Cache::store( 'get_minimal_price:' . $id_product, $price );
    }

    return $price;
  }

  public static function product_categories( $product_id )
  {
    global $mdb;

    if ( $parent_id = $mdb -> get( 'pp_shop_products', 'parent_id', [ 'id' => $product_id ] ) )
      return \R::getAll( 'SELECT category_id FROM pp_shop_products_categories WHERE product_id = ?', [ $parent_id ] );
    else
      return \R::getAll( 'SELECT category_id FROM pp_shop_products_categories WHERE product_id = ?', [ $product_id ] );
  }

  public static function product_name( $product_id )
  {
    global $mdb, $lang_id;

    if ( !$product_name = \Cache::fetch( 'product_name' . $lang_id . '_' . $product_id ) )
    {
      $product_name = $mdb -> get( 'pp_shop_products_langs', 'name', [ 'AND' => [ 'product_id' => (int)$product_id, 'lang_id' => $lang_id ] ] );

      \Cache::store( 'product_name' . $lang_id . '_' . $product_id, $product_name );
    }

    return $product_name;
  }

  public static function product_image( $product_id )
  {
    global $mdb;

    if ( !$product_image = \Cache::fetch( 'product_image:' . $product_id ) )
    {
      $results = $mdb -> query( 'SELECT src FROM pp_shop_products_images WHERE product_id = :product_id ORDER BY o ASC LIMIT 1', [ ':product_id' => (int)$product_id ] ) -> fetchAll( \PDO::FETCH_ASSOC );
      $product_image = $results[ 0 ][ 'src' ];

      \Cache::store( 'product_image:' . $product_id, $product_image );
    }

    return $product_image;
  }

  public static function product_wp( $product_id )
  {
    global $mdb;

    $cacheHandler = new \CacheHandler();
    $cacheKey = "\front\factory\ShopProduct::product_wp:$product_id";

    $objectData = $cacheHandler -> get( $cacheKey );

    if ( !$objectData )
    {
      $product_wp = $mdb -> get( 'pp_shop_products', 'wp', [ 'id' => $product_id ] );

      $cacheHandler -> set( $cacheKey, $product_wp );
    }
    else
    {
      return unserialize( $objectData );
    }
    return $product_wp;
  }

  public static function random_products( $product_id, $lang_id = 'pl' )
  {
    global $mdb;

    if ( !$products = \Cache::fetch( 'random_productsa_' . $product_id . '_' . $lang_id ) )
    {
      $results = $mdb -> query( 'SELECT id FROM pp_shop_products WHERE status = 1 ORDER BY RAND() LIMIT 6' ) -> fetchAll();
      if ( is_array( $results ) and!empty( $results ) )
        foreach ( $results as $row )
          $products[] = \front\factory\ShopProduct::product_details( $row[ 'id' ], $lang_id );

      \Cache::store( 'random_products_' . $product_id . '_' . $lang_id, $products );
    }

    return $products;
  }

  public static function promoted_products( $limit = 6 )
  {
    global $mdb;

    if ( !$products = \Cache::fetch( "promoted_products-$limit" ) )
    {
      $results = $mdb -> query( 'SELECT id FROM pp_shop_products WHERE status = 1 AND promoted = 1 ORDER BY RAND() LIMIT ' . $limit ) -> fetchAll();
      if ( is_array( $results ) and!empty( $results ) )
        foreach ( $results as $row )
          $products[] = $row[ 'id' ];

      \Cache::store( "promoted_products-$limit", $products );
    }

    return $products;
  }

  public static function top_products( $limit = 6 )
  {
    global $mdb;

    $date_30_days_ago = date('Y-m-d', strtotime('-30 days'));

    $products = $mdb -> query( "SELECT COUNT(0) AS sell_count, psop.parent_product_id FROM pp_shop_order_products AS psop INNER JOIN pp_shop_orders AS pso ON pso.id = psop.order_id WHERE pso.date_order >= '$date_30_days_ago' GROUP BY parent_product_id ORDER BY sell_count DESC")->fetchAll(\PDO::FETCH_ASSOC);

    foreach ( $products as $product )
    {
      if ( \front\factory\ShopProduct::is_product_active( $product['parent_product_id'] ) )
        $product_ids[] = $product['parent_product_id'];
    }

    return $product_ids;
  }

  public static function new_products( $limit = 10 ) {
    global $mdb;

    $results = $mdb->query("
        SELECT id
        FROM pp_shop_products
        WHERE status = 1
        ORDER BY date_add DESC
        LIMIT $limit
    ")->fetchAll(\PDO::FETCH_ASSOC);

    return array_column($results, 'id');
  }

  public static function product_details( $product_id, $lang_id )
  {
    global $mdb;

    if ( !$product_id )
      return false;

    $cacheHandler = new \CacheHandler();
    $cacheKey = "\front\factory\ShopProduct::product_details:$product_id:$lang_id";

    $objectData = $cacheHandler->get($cacheKey);

    if ( !$objectData )
    {
      $product = $mdb -> get( 'pp_shop_products', '*', [ 'id' => (int)$product_id ] );

      $results = $mdb -> select( 'pp_shop_products_langs', '*', [ 'AND' => [ 'product_id' => (int)$product_id, 'lang_id' => $lang_id ] ] );
      if ( is_array( $results ) )
        foreach ( $results as $row )
        {
          if ( $row[ 'copy_from' ] )
          {
            $results2 = $mdb -> select( 'pp_shop_products_langs', '*', [ 'AND' => [ 'product_id' => (int)$product_id, 'lang_id' => $row[ 'copy_from' ] ] ] );
            if ( is_array( $results2 ) )
              foreach ( $results2 as $row2 )
                $product[ 'language' ] = $row2;
          }
          else
            $product[ 'language' ] = $row;
        }

      $results = $mdb -> query( 'SELECT '
          . 'DISTINCT( attribute_id ) '
          . 'FROM '
          . 'pp_shop_products_attributes AS pspa '
          . 'INNER JOIN pp_shop_attributes AS psa ON psa.id = pspa.attribute_id '
          . 'WHERE '
          . 'product_id = ' . (int)$product_id . ' '
          . 'ORDER BY '
          . 'o ASC' ) -> fetchAll();
      if ( is_array( $results ) )
        foreach ( $results as $row )
        {
          $row[ 'require' ] = $mdb -> get( 'pp_shop_attributes',
            'required',
            [ 'id' => $row[ 'attribute_id' ] ]
          );

          $row[ 'type' ] = $mdb -> get( 'pp_shop_attributes',
            'type',
            [ 'id' => $row[ 'attribute_id' ] ]
          );

          $row[ 'language' ] = $mdb -> get( 'pp_shop_attributes_langs',
            [ 'name' ],
            [ 'AND' =>
                [ 'attribute_id' => $row[ 'attribute_id' ], 'lang_id' => $lang_id ]
            ]
          );

          $results2 = $mdb -> query( 'SELECT '
              . 'value_id, is_default '
              . 'FROM '
              . 'pp_shop_products_attributes AS pspa '
              . 'INNER JOIN pp_shop_attributes_values AS psav ON psav.id = pspa.value_id '
              . 'WHERE '
              . 'product_id = :product_id '
              . 'AND '
              . 'pspa.attribute_id = :attribute_id ',
              [
                  ':product_id'   => $product_id,
                  ':attribute_id' => $row[ 'attribute_id' ]
              ]
            ) -> fetchAll( \PDO::FETCH_ASSOC );

          if ( is_array( $results2 ) )
            foreach ( $results2 as $row2 )
            {
              $row2[ 'language' ] = $mdb -> get( 'pp_shop_attributes_values_langs',
                [ 'name', 'value' ],
                [ 'AND' =>
                    [ 'value_id' => $row2[ 'value_id' ], 'lang_id' => $lang_id ]
                ]
              );
              $row[ 'values' ][] = $row2;
            }

          $product[ 'attributes' ][] = $row;
        }

      $product[ 'images' ] = $mdb -> select( 'pp_shop_products_images', '*', [ 'product_id' => (int)$product_id, 'ORDER' => [ 'o' => 'ASC', 'id' => 'ASC' ] ] );
      $product[ 'files' ] = $mdb -> select( 'pp_shop_products_files', '*', [ 'product_id' => (int)$product_id ] );
      $product[ 'categories' ] = $mdb -> select( 'pp_shop_products_categories', 'category_id', [ 'product_id' => (int)$product_id ] );

      $product[ 'products_related' ] = $mdb -> select( 'pp_shop_products_related', 'product_related_id', [ 'product_id' => (int)$product_id ] );

      $products_sets_1 = $mdb -> select( 'pp_shop_products_sets', 'product_sets_id', [ 'product_id' => (int)$product_id ] );
      $products_sets_2 = $mdb -> select( 'pp_shop_products_sets', 'product_id', [ 'product_sets_id' => (int)$product_id ] );
      $products_sets = array_unique( array_merge( $products_sets_1, $products_sets_2 ) );

      $product[ 'products_sets' ] = $products_sets;

      $attributes = $mdb -> select( 'pp_shop_products_attributes', [ 'attribute_id', 'value_id' ], [ 'product_id' => (int)$product_id ] );
      if ( is_array( $attributes ) ): foreach ( $attributes as $attribute ):
          $attributes_tmp[ $attribute[ 'attribute_id' ] ][] = $attribute[ 'value_id' ];
        endforeach;
      endif;

      if ( is_array( $attributes_tmp ) )
        $product[ 'permutations' ] = \S::array_cartesian_product( $attributes_tmp );

      $cacheHandler -> set( $cacheKey, $product );
    }
    else
    {
      return unserialize($objectData);
    }

    return $product;
  }

  public static function warehouse_message_zero( $id_product, $lang_id )
  {
    global $mdb, $lang_id;
    return $mdb -> get( 'pp_shop_products_langs', 'warehouse_message_zero', [ 'AND' => [ 'product_id' => $id_product, 'lang_id' => $lang_id ] ] );
  }

  public static function warehouse_message_nonzero( $id_product, $lang_id )
  {
    global $mdb, $lang_id;
    return $mdb -> get( 'pp_shop_products_langs', 'warehouse_message_nonzero', [ 'AND' => [ 'product_id' => $id_product, 'lang_id' => $lang_id ] ] );
  }

  public static function permutation_quantity( $id_product, $permutation, bool $is_multichoice )
  {
    global $mdb;

    if ( !$is_multichoice )
      return $mdb -> get( 'pp_shop_products_stock', 'quantity', [ 'AND' => [ 'id_product' => $id_product, 'permutation' => 0 ] ] );

    if ( is_array( $permutation ) )
    {
      foreach ( $permutation as $key => $val )
      {
        $permutation_id .= $val;
        if ( $val != end( $permutation ) )
          $permutation_id .= '_';
      }
    }
    else
      $permutation_id = $permutation;

    return $mdb -> get( 'pp_shop_products_stock', 'quantity', [ 'AND' => [ 'id_product' => $id_product, 'permutation' => $permutation_id ] ] );
  }

  //TO:DO do usunięcia
  public static function product_both_price( $product_id )
  {
    global $mdb;
    return $mdb -> get( 'pp_shop_products', [ 'price_brutto', 'price_brutto_promo' ], [ 'id' => (int)$product_id ] );
  }

  //TO:DO do usunięcia
  public static function product_price( $product_id )
  {
    global $mdb;

    $product = $mdb -> get( 'pp_shop_products', [ 'price_brutto', 'price_brutto_promo', 'vat' ], [ 'id' => (int)$product_id ] );
    if ( $product[ 'price_brutto_promo' ] )
      return $product[ 'price_brutto_promo' ];
    else
      return $product[ 'price_brutto' ];
  }

}