<?php
namespace shop;

class Order implements \ArrayAccess
{
  public $id;
  public $products;
  public $statuses;
  public $status;
  public $client_email;
  public $sellasist_order_id;
  public $summary;
  public $baselinker_order_id;
  public $apilo_order_id;
  public $date_order;
  public $payment_method_id;
  public $transport_cost;
  public $number;

  public function __construct( int $order_id, $hash = '', $przelewy24_hash = '' )
  {
    global $mdb;

    if ( $order_id )
    {
      $result = $mdb -> get( 'pp_shop_orders', '*', [ 'id' => $order_id ] );
      if ( \S::is_array_fix( $result ) ) foreach ( $result as $key => $val )
        $this -> $key = $val;
    }

    if ( $hash )
    {
      $result = $mdb -> get( 'pp_shop_orders', '*', [ 'hash' => $hash ] );
      if ( \S::is_array_fix( $result ) ) foreach ( $result as $key => $val )
        $this -> $key = $val;
    }

    if ( $przelewy24_hash )
    {
      $result = $mdb -> get( 'pp_shop_orders', '*', [ 'przelewy24_hash' => $przelewy24_hash ] );
      if ( \S::is_array_fix( $result ) ) foreach ( $result as $key => $val )
        $this -> $key = $val;
    }

    $this -> products = $mdb -> select( 'pp_shop_order_products', '*', [ 'order_id' => $order_id ] );
    $this -> statuses = $mdb -> select( 'pp_shop_order_statuses', '*', [ 'order_id' => $order_id, 'ORDER' => [ 'id' => 'DESC' ] ] );
  }

  static public function notes_save( int $order_id, $notes )
  {
    global $mdb;
    return $mdb -> update( 'pp_shop_orders', [ 'notes' => $notes ], [ 'id' => $order_id ] );
  }

  public static function order_statuses()
  {
    global $mdb;
    $results = $mdb -> select( 'pp_shop_statuses', [ 'id', 'status' ], [ 'ORDER' => [ 'o' => 'ASC' ] ] );
    if ( \S::is_array_fix( $results ) ) foreach ( $results as $row )
      $statuses[ (int)$row['id'] ] = $row['status'];
    return $statuses;
  }

  public function update_baselinker_order_status_date( $date )
  {
    global $mdb;
    return $mdb -> update( 'pp_shop_orders', [ 'baselinker_order_status_date' => $date ], [ 'id' => $this -> id ] );
  }

  public function update_aplio_order_status_date( $date )
  {
    global $mdb;
    return $mdb -> update( 'pp_shop_orders', [ 'apilo_order_status_date' => $date ], [ 'id' => $this -> id ] );
  }

  // set_as_unpaid
  public function set_as_unpaid() {
    global $mdb;

    $sellasist_settings = \admin\factory\Integrations::sellasist_settings();
    if ( $sellasist_settings['enabled'] and $sellasist_settings['api_code'] and $sellasist_settings['sync_orders'] ) {
      if ( $this -> sellasist_order_id ) {
        $ch = curl_init();
        curl_setopt( $ch, CURLOPT_URL, "https://projectpro.sellasist.pl/api/v1/orders/" . $this -> sellasist_order_id );
        curl_setopt( $ch, CURLOPT_POST, 1 );
        curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "PUT");
        curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( [
          'paid' => 0,
          'payment_status' => 'unpaid'
        ] ) );
        curl_setopt( $ch, CURLOPT_HTTPHEADER, array(
          "accept: application/json",
          "apiKey: " . $sellasist_settings['api_code'],
          "Content-Type: application/json"
        ) );
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
        curl_exec( $ch );
        curl_close( $ch );
      }
    }

    $mdb -> update( 'pp_shop_orders', [ 'paid' => 0 ], [ 'id' => $this -> id ] );
    return true;
  }

  // set_as_paid
  public function set_as_paid( $send_email = false )
  {
    global $mdb, $config;

    $sellasist_settings = \admin\factory\Integrations::sellasist_settings();
    if ( $sellasist_settings['enabled'] and $sellasist_settings['api_code'] and $sellasist_settings['sync_orders'] )
    {
      if ( $this -> sellasist_order_id )
      {
        $ch = curl_init();
        curl_setopt( $ch, CURLOPT_URL, "https://projectpro.sellasist.pl/api/v1/orders/" . $this -> sellasist_order_id );
        curl_setopt( $ch, CURLOPT_POST, 1 );
        curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "PUT");
        curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( [
          'paid' => str_replace( ',', '.', $this -> summary ),
          'payment_status' => 'paid'
        ] ) );
        curl_setopt( $ch, CURLOPT_HTTPHEADER, array(
          "accept: application/json",
          "apiKey: " . $sellasist_settings['api_code'],
          "Content-Type: application/json"
        ) );
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
        curl_exec( $ch );
        curl_close( $ch );
      }
    }

    $baselinker_settings = \admin\factory\Integrations::baselinker_settings();
    if ( $baselinker_settings['enabled'] and $baselinker_settings['api_code'] and $baselinker_settings['sync_orders'] )
    {
      if ( $this -> baselinker_order_id )
      {
        $ch = curl_init();
        curl_setopt( $ch, CURLOPT_URL, "https://api.baselinker.com/connector.php" );
        curl_setopt( $ch, CURLOPT_POST, 1 );
        curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( [
          'token' => $baselinker_settings['api_code'],
          'method' => 'setOrderPayment',
          'parameters' => json_encode( [
            'order_id' => $this -> baselinker_order_id,
            'payment_done' => $this -> summary,
            'payment_date' => time( 'Y-m-d H:i:s' )
          ] )
        ] ) );
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
        curl_exec( $ch );
        curl_close( $ch );
      }
    }

    // apilo
    $apilo_settings = \admin\factory\Integrations::apilo_settings();
    if ( $apilo_settings['enabled'] and $apilo_settings['access-token'] and $apilo_settings['sync_orders'] )
    {
      // put data to file
      if ( $config['debug']['apilo'] )
      {
        file_put_contents( $_SERVER['DOCUMENT_ROOT'] . '/logs/apilo.txt', date( 'Y-m-d H:i:s' ) . " --- SET AS PAID\n\n", FILE_APPEND );
        file_put_contents( $_SERVER['DOCUMENT_ROOT'] . '/logs/apilo.txt', print_r( $this, true ) . "\n\n", FILE_APPEND );
      }

      if ( $this -> apilo_order_id )
      {
        $payment_date = new \DateTime( $this -> date_order );
        $access_token = \admin\factory\Integrations::apilo_get_access_token();

        $ch = curl_init();
        curl_setopt( $ch, CURLOPT_URL, "https://projectpro.apilo.com/rest/api/orders/" . $this -> apilo_order_id . '/payment/' );
        curl_setopt( $ch, CURLOPT_POST, 1 );
        curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( [
          'amount' => str_replace( ',', '.', $this -> summary ),
          'paymentDate' => $payment_date -> format('Y-m-d\TH:i:s\Z'),
          'type' => 1
        ] ) );
        curl_setopt( $ch, CURLOPT_HTTPHEADER, [
          "Authorization: Bearer " . $access_token,
          "Accept: application/json"
        ] );
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
        $apilo_response = curl_exec( $ch );

        // put response to log
        if ( $config['debug']['apilo'] )
          file_put_contents( $_SERVER['DOCUMENT_ROOT'] . '/logs/apilo.txt', print_r( $apilo_response, true ) . "\n\n", FILE_APPEND );

        curl_close( $ch );
      }
    }

    $mdb -> update( 'pp_shop_orders', [ 'paid' => 1 ], [ 'id' => $this -> id ] );
    $this -> update_status( 1, $send_email );

    $dir_logs = $_SERVER['DOCUMENT_ROOT'] . '/logs/';
    if ( !is_dir( $dir_logs ) )
      mkdir( $dir_logs, 0777, true );

    $file = $dir_logs . date( 'Y-m-d' ) . '-order-set-as-paid.txt';
    $content = date( 'Y-m-d H:i:s' ) . ' | ' . $this -> id . ' | ' . $this -> number . ' | ' . $this -> summary . ' | ' . $this -> client_email . "\n";
    $content .= print_r( $apilo_response, true ) . "\n\n";
    file_put_contents( $file, $content, FILE_APPEND );

    return true;
  }

  // zmiana statusu zamówienia
  public function update_status( int $status, int $email_send )
  {
    global $mdb, $config;

    if ( $this -> status == $status )
      return false;

    if ( $mdb -> update( 'pp_shop_orders', [ 'status' => $status ], [ 'id' => $this -> id ] ) )
    {
      $mdb -> insert( 'pp_shop_order_statuses', [
        'order_id' => $this -> id,
        'status_id' => $status,
        'mail' => $email_send
      ] );

      if ( $email_send )
      {
        $this -> status = $status;
        $response['email'] = $this -> send_status_change_email();
      }

      $response['result'] = true;

      $sellasist_settings = \admin\factory\Integrations::sellasist_settings();
      if ( $sellasist_settings['enabled'] and $sellasist_settings['api_code'] and $sellasist_settings['sync_orders'] )
      {
        if ( $this -> sellasist_order_id )
        {
          $ch = curl_init();
          curl_setopt( $ch, CURLOPT_URL, "https://projectpro.sellasist.pl/api/v1/orders/" . $this -> sellasist_order_id );
          curl_setopt( $ch, CURLOPT_POST, 1 );
          curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "PUT");
          curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( [
            'status' => \front\factory\ShopStatuses::get_sellasist_status_id( $status )
          ] ) );
          curl_setopt( $ch, CURLOPT_HTTPHEADER, array(
            "accept: application/json",
            "apiKey: " . $sellasist_settings['api_code'],
            "Content-Type: application/json"
          ) );
          curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
          curl_exec( $ch );
          curl_close( $ch );
        }
      }

      $baselinker_settings = \admin\factory\Integrations::baselinker_settings();
      if ( $baselinker_settings['enabled'] and $baselinker_settings['api_code'] and $baselinker_settings['sync_orders'] )
      {
        if ( $this -> baselinker_order_id )
        {
          $ch = curl_init();
          curl_setopt( $ch, CURLOPT_URL, "https://api.baselinker.com/connector.php" );
          curl_setopt( $ch, CURLOPT_POST, 1 );
          curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( [
            'token' => $baselinker_settings['api_code'],
            'method' => 'setOrderStatus',
            'parameters' => json_encode( [
              'order_id' => $this -> baselinker_order_id,
              'status_id' => \shop\ShopStatus::get_baselinker_status_by_shop_status( $status )
            ] )
          ] ) );
          curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
          $curl_result = curl_exec( $ch );
          curl_close( $ch );
        }
      }

      // apilo
      $apilo_settings = \admin\factory\Integrations::apilo_settings();
      if ( $apilo_settings['enabled'] and $apilo_settings['access-token'] and $apilo_settings['sync_orders'] )
      {
        // put data to file
        if ( $config['debug']['apilo'] )
        {
          file_put_contents( $_SERVER['DOCUMENT_ROOT'] . '/logs/apilo.txt', date( 'Y-m-d H:i:s' ) . " --- UPDATE STATUS\n\n", FILE_APPEND );
          file_put_contents( $_SERVER['DOCUMENT_ROOT'] . '/logs/apilo.txt', print_r( $this, true ) . "\n\n", FILE_APPEND );
        }

        if ( $this -> apilo_order_id )
        {
          $access_token = \admin\factory\Integrations::apilo_get_access_token();

          $ch = curl_init();
          curl_setopt( $ch, CURLOPT_URL, "https://projectpro.apilo.com/rest/api/orders/" . $this -> apilo_order_id . '/status/' );
          curl_setopt( $ch, CURLOPT_POST, 1 );
          curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "PUT");
          curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( [
            'id' => $this -> apilo_order_id,
            'status' => (int)\front\factory\ShopStatuses::get_apilo_status_id( $status )
          ] ) );
          curl_setopt( $ch, CURLOPT_HTTPHEADER, [
            "Authorization: Bearer " . $access_token,
            "Accept: application/json",
            "Content-Type: application/json"
          ] );
          curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
          $apilo_result = curl_exec( $ch );

          // put response to log
          if ( $config['debug']['apilo'] )
            file_put_contents( $_SERVER['DOCUMENT_ROOT'] . '/logs/apilo.txt', print_r( $apilo_result, true ) . "\n\n", FILE_APPEND );

          curl_close( $ch );
        }
      }

      return $response;
    }
    return false;
  }

  // ponowne wysłanie maila o złożonym zamówieniu
  public function order_resend_confirmation_email()
  {
    global $settings;

    $order = \front\factory\ShopOrder::order_details( $this -> id );

    $mail_order = \Tpl::view( 'shop-order/mail-summary', [
      'settings' => $settings,
      'order' => $order
      ] );

    $settings[ 'ssl' ] ? $base = 'https' : $base = 'http';

    $regex = "-(<img[^>]+src\s*=\s*['\"])(((?!'|\"|https?://).)*)(['\"][^>]*>)-i";
    $mail_order = preg_replace( $regex, "$1" . $base . "://" . $_SERVER[ 'SERVER_NAME' ] . "$2$4", $mail_order );

    $regex = "-(<a[^>]+href\s*=\s*['\"])(((?!'|\"|https?://).)*)(['\"][^>]*>)-i";
    $mail_order = preg_replace( $regex, "$1" . $base . "://" . $_SERVER[ 'SERVER_NAME' ] . "$2$4", $mail_order );

    \S::send_email( $this -> client_email, \S::lang( 'potwierdzenie-zamowienia-ze-sklepu' ) . ' ' . $settings[ 'firm_name' ], $mail_order );
    \S::send_email( $settings[ 'contact_email' ], 'Nowe zamówienie / ' . $settings[ 'firm_name' ] . ' / ' . $order['number'] . ' - ' . $order['client_surname'] . ' ' . $order['client_name'], $mail_order );

    return true;
  }

  // wysłanie maila o zmianie statusu
  public function send_status_change_email()
  {
    if ( !$this -> client_email )
      return false;

    $order_statuses = self::order_statuses();

    $firm_name = \front\factory\Settings::get_single_settings_value( 'firm_name' );

    switch( $this -> status ):
      case 0:
        $subject = str_replace( '[NUMER]', $this -> number, $firm_name . ' - zamówienie [NUMER] zostało złożone' );
      break;
      case 1:
        $subject = str_replace( '[NUMER]', $this -> number, $firm_name . ' - zamówienie [NUMER] zostało opłacone' );
      break;
      case 2:
        $subject = str_replace( '[NUMER]', $this -> number, $firm_name . ' - płatność za zamówienie [NUMER] została odrzucona' );
      break;
      case 3:
        $subject = str_replace( '[NUMER]', $this -> number, $firm_name . ' - płatność za zamówienie [NUMER] jest sprawdzania ręcznie' );
      break;
      case 4:
        $subject = str_replace( '[NUMER]', $this -> number, $firm_name . ' - zamówienie [NUMER] zostało przyjęte do realizacji' );
      break;
      case 5:
        $subject = str_replace( '[NUMER]', $this -> number, $firm_name . ' - zamówienie [NUMER] zostało wysłane' );
      break;
      case 6:
        $subject = str_replace( '[NUMER]', $this -> number, $firm_name . ' - zamówienie [NUMER] zostało zrealizowane' );
      break;
      case 7:
        $subject = str_replace( '[NUMER]', $this -> number, $firm_name . ' - zamówienie [NUMER] zostało przygotowane go wysłania' );
      break;
      case 8:
        $subject = str_replace( '[NUMER]', $this -> number, $firm_name . ' - zamówienie [NUMER] zostało anulowane' );
      break;
    endswitch;

    $email = new \Email( 0 );
    $email -> load_by_name( '#sklep-zmiana-statusu-zamowienia' );

    $email -> text = str_replace( '[NUMER_ZAMOWIENIA]', $this -> number, $email -> text );
    $email -> text = str_replace( '[DATA_ZAMOWIENIA]', date( 'Y/m/d', strtotime( $this -> date_order ) ), $email -> text );
    $email -> text = str_replace( '[STATUS]', $order_statuses[ $this -> status ], $email -> text );

    return $email -> send( $this -> client_email, $subject, true );
  }

  // wyliczanie wartości zamówienia podczas edycji zamówienia
  static public function calculate_order_summary_by_admin( int $order_id )
  {
    global $mdb;

    $rows = $mdb -> select( 'pp_shop_order_products', '*', [ 'order_id' => $order_id ] );
    if ( \S::is_array_fix( $rows ) ) foreach ( $rows as $row )
    {
      if ( $row['price_brutto_promo'] )
        $summary += $row['price_brutto_promo'] * $row['quantity'];
      else
        $summary += $row['price_brutto'] * $row['quantity'];
    }

    return $summary + $mdb -> get( 'pp_shop_orders', 'transport_cost', [ 'id' => $order_id ] );
  }

  // ADMIN - usunięcie zamówienia
  static public function order_delete( int $order_id )
  {
    global $mdb;
    return $mdb -> delete( 'pp_shop_orders', [ 'id' => $order_id ] );
  }

  // ADMIN - zmiana zamówienia
  static public function order_save_by_admin( int $order_id, string $client_name, string $client_surname, string $client_firm, string $client_street, string $client_postal_code, string $client_city, string $client_email,
    int $transport_id, string $inpost_paczkomat, int $payment_method_id )
  {
    global $mdb, $user;

    $mdb -> update( 'pp_shop_orders', [
              'client_name' => $client_name,
              'client_surname' => $client_surname,
              'client_firm' => $client_firm,
              'client_street' => $client_street,
              'client_postal_code' => $client_postal_code,
              'client_city' => $client_city,
              'client_email' => $client_email,
              'transport_id' =>  $transport_id,
              'transport' => $mdb -> get( 'pp_shop_transports', 'name_visible', [ 'id' => $transport_id ] ),
              'transport_cost' => $mdb -> get( 'pp_shop_transports', 'cost', [ 'id' => $transport_id ] ),
              'transport_description' => $mdb -> get( 'pp_shop_transports', 'description', [ 'id' => $transport_id ] ),
              'inpost_paczkomat' => $inpost_paczkomat,
              'payment_method_id' => $payment_method_id,
              'payment_method' => $mdb -> get( 'pp_shop_payment_methods', 'name', [ 'id' => $payment_method_id ] ),
            ], [
              'id' => $order_id
            ] );

    $mdb -> update( 'pp_shop_orders', [
              'summary' => \shop\Order::calculate_order_summary_by_admin( $order_id )
            ], [
              'id' => $order_id
            ] );

    \Log::save_log( 'Zamówienie zmienione przez administratora | ID: ' . $order_id, $user['id'] );

    return true;
  }

  public function offsetExists( $offset )
  {
    return isset( $this -> $offset );
  }

  public function offsetGet( $offset )
  {
    return $this -> $offset;
  }

  public function offsetSet( $offset, $value )
  {
    $this -> $offset = $value;
  }

  public function offsetUnset( $offset )
  {
    unset( $this -> $offset );
  }
}