<?php

namespace Sibs\Stargate\Models;

use Sibs\Stargate\Config\SibsConfig;
use Sibs\Stargate\Constants\Plugin;

defined('ABSPATH') || exit;

class SibsGeneralModels
{
    /**
     * Get Transactions from database.
     *
     * @return array
     */
    public static function get_transaction(\WC_Order $wc_order)
    {
        global $wpdb;

        $tablePrefix = $wpdb->prefix.Plugin::PLUGIN_PREFIX;
        $tableName = "{$tablePrefix}_transaction";
        $query = "SELECT * FROM `{$tableName}`
      WHERE `order_no` = %s";
        $query_prepare = $wpdb->prepare($query, $wc_order->get_id());
        $result = $wpdb->get_row($query_prepare, ARRAY_A);

        return $result;
    }

    /**
     * Get Transaction reference_id.
     *
     * @return array
     */
    public static function get_transaction_by_reference_id(string $reference_id)
    {
        global $wpdb;

        $tablePrefix = $wpdb->prefix.Plugin::PLUGIN_PREFIX;
        $tableName = "{$tablePrefix}_transaction";
        $query = "SELECT * FROM `{$tableName}`
      WHERE `reference_id` = %s";
        $query_prepare = $wpdb->prepare($query, $reference_id);
        $result = $wpdb->get_row($query_prepare, ARRAY_A);

        return $result;
    }

    /**
     * Get Current User Card Tokens.
     *
     * @return array
     */
    public static function get_current_user_card_tokens()
    {
        global $wpdb;

        $tablePrefix = $wpdb->prefix.Plugin::PLUGIN_PREFIX;
        $tableName = "{$tablePrefix}_card_tokens";
        $query = "SELECT `token_type`, `value`
      FROM `{$tableName}`
      WHERE `id_customer` = %s
    ";

        $query_prepare = $wpdb->prepare($query, get_current_user_id());
        $registered_payments = $wpdb->get_results($query_prepare, ARRAY_A);

        $tokenFunction = function (array $tokenDB) {
            return [
                'tokenType' => $tokenDB['token_type'],
                'value' => $tokenDB['value'],
            ];
        };

        return array_map($tokenFunction, $registered_payments);
    }

    /**
     * Get Unprocessed Webhook calls.
     *
     * @return array
     */
    public static function get_unprocessed_webhook_calls()
    {
        global $wpdb;

        $tablePrefix = $wpdb->prefix.Plugin::PLUGIN_PREFIX;
        $tableName = "{$tablePrefix}_webhook_retry";
        $query = "SELECT * FROM `{$tableName}`
      WHERE `processed_qty` <= ".Plugin::WEBHOOK_RETRY_QTY
    ." AND `processed_at` IS NULL
      AND `created_at` < '".SibsConfig::getStoreCurrentTime('Y-m-d H:i:s', strtotime('-5 minutes'))."'";
        $query_prepare = $wpdb->prepare($query);
        $unprocessed_webhook_calls = $wpdb->get_results($query_prepare, ARRAY_A);

        return $unprocessed_webhook_calls ?? [];
    }

    /**
     * Get Webhook call by payload.
     *
     * @return array
     */
    public static function get_webhook_call_by_payload(string $payload)
    {
        global $wpdb;

        $tablePrefix = $wpdb->prefix.Plugin::PLUGIN_PREFIX;
        $tableName = "{$tablePrefix}_webhook_retry";
        $query = "SELECT * FROM `{$tableName}`
      WHERE `payload` = %s";
        $query_prepare = $wpdb->prepare($query, $payload);
        $webhook_call = $wpdb->get_row($query_prepare, ARRAY_A);

        return $webhook_call;
    }

    // UPDATE

    /**
     * Update Payment Status at Transactions Log.
     */
    public static function update_transaction(\WC_Order $wc_order, array $data)
    {
        global $wpdb;

        $tablePrefix = $wpdb->prefix.Plugin::PLUGIN_PREFIX;
        $tableName = "{$tablePrefix}_transaction";
        $where = ['order_no' => $wc_order->get_id()];
        $dataFormat = null;
        $whereFormat = ['%d'];

        return $wpdb->update(
            $tableName,
            $data,
            $where,
            $dataFormat,
            $whereFormat
        );
    }

    /**
     * Update Payment Status at Transactions Log.
     */
    public static function update_transaction_by_reference_id(string $reference_id, array $data)
    {
        global $wpdb;

        $tablePrefix = $wpdb->prefix.Plugin::PLUGIN_PREFIX;
        $tableName = "{$tablePrefix}_transaction";
        $where = ['reference_id' => $reference_id];
        $dataFormat = null;
        $whereFormat = ['%d'];

        return $wpdb->update(
            $tableName,
            $data,
            $where,
            $dataFormat,
            $whereFormat
        );
    }

    /**
     * Update Payment Status at Transactions.
     */
    public static function update_transaction_status(\WC_Order $wc_order, string $payment_status)
    {
        global $wpdb;

        $tablePrefix = $wpdb->prefix.Plugin::PLUGIN_PREFIX;
        $tableName = "{$tablePrefix}_transaction";
        $data = ['payment_status' => $payment_status];
        $where = ['order_no' => $wc_order->get_id()];
        $dataFormat = ['%s'];
        $whereFormat = ['%d'];

        return $wpdb->update(
            $tableName,
            $data,
            $where,
            $dataFormat,
            $whereFormat
        );
    }

    /**
     * Update Payment Status at database wp_post
     * Update wp_post post_status if change payment status at backend.
     */
    public static function sibs_update_posts_status(\WC_Order $wc_order, string $payment_status)
    {
        global $wpdb;

        $tableName = "{$wpdb->prefix}posts";
        $data = ['post_status' => $payment_status];
        $where = ['ID' => $wc_order->get_id()];
        $dataFormat = ['%s'];
        $whereFormat = ['%d'];

        return $wpdb->update(
            $tableName,
            $data,
            $where,
            $dataFormat,
            $whereFormat
        );
    }

    /**
     * Update Webhook Calls.
     *
     * @param int $webhook_id
     */
    public static function update_webhook_calls($webhook_id, array $webhook)
    {
        global $wpdb;

        $tablePrefix = $wpdb->prefix.Plugin::PLUGIN_PREFIX;
        $tableName = "{$tablePrefix}_webhook_retry";

        $data = [];
        $dataFormat = [];

        if (isset($webhook['notification_id'])) {
            $data['notification_id'] = $webhook['notification_id'];
            $dataFormat[] = '%s';
        }

        if (isset($webhook['decoded_payload'])) {
            $data['decoded_payload'] = json_encode($webhook['decoded_payload']);
            $dataFormat[] = '%s';
        }

        if (isset($webhook['exception'])) {
            $data['exception'] = $webhook['exception'];
            $dataFormat[] = '%s';
        }

        if (isset($webhook['arrived'])) {
            $data['arrived'] = $webhook['arrived'];
            $dataFormat[] = '%s';
        }

        if (isset($webhook['processed_qty'])) {
            $data['processed_qty'] = $webhook['processed_qty'];
            $dataFormat[] = '%s';
        }

        if (isset($webhook['processed_at'])) {
            $data['processed_at'] = $webhook['processed_at'];
            $dataFormat[] = '%s';
        }

        $where = ['id' => $webhook_id];
        $whereFormat = ['%d'];

        return $wpdb->update(
            $tableName,
            $data,
            $where,
            $dataFormat,
            $whereFormat
        );
    }

    // SAVE

    /**
     * Save or Update Transaction.
     */
    public static function create_or_update_transaction(array $transaction)
    {
        global $wpdb;

        $wc_order = wc_get_order($transaction['order_no'] ?? null);
        $hasTransaction = self::get_transaction($wc_order);

        if (!$hasTransaction) {
            $tablePrefix = $wpdb->prefix.Plugin::PLUGIN_PREFIX;
            $tableName = "{$tablePrefix}_transaction";
            $data = [
                'order_no' => $transaction['order_no'],
                'customer_id' => $transaction['customer_id'],
                'reference_id' => $transaction['reference_id'],
                'payment_id' => $transaction['payment_id'],
                'payment_type' => $transaction['payment_type'],
                'payment_brand' => $transaction['payment_brand'],
                'payment_status' => $transaction['payment_status'],
                'date' => $transaction['date'],
                'currency' => $transaction['currency'],
                'amount' => $transaction['amount'],
            ];

            $dataFormat = [
                '%d', '%d', '%s', '%s', '%s',
                '%s', '%s', '%s', '%s', '%s',
            ];

            if (!empty($transaction['captured_id'])) {
                $data['captured_id'] = $transaction['captured_id'];
                $dataFormat[] = '%s';
            }

            if (!empty($transaction['refunded_id'])) {
                $data['refunded_id'] = $transaction['refunded_id'];
                $dataFormat[] = '%s';
            }

            if (!empty($transaction['additional_information'])) {
                $data['additional_information'] = $transaction['additional_information'];
                $dataFormat[] = '%s';
            }

            if (!empty($transaction['capture_status'])) {
                $data['capture_status'] = $transaction['capture_status'];
                $dataFormat[] = '%s';
            }

            if (!empty($transaction['captured_amount'])) {
                $data['captured_amount'] = $transaction['captured_amount'];
                $dataFormat[] = '%d';
            }

            if (!empty($transaction['capture_information'])) {
                $data['capture_information'] = $transaction['capture_information'];
                $dataFormat[] = '%s';
            }

            if (!empty($transaction['refund_status'])) {
                $data['refund_status'] = $transaction['refund_status'];
                $dataFormat[] = '%s';
            }

            if (!empty($transaction['refunded_amount'])) {
                $data['refunded_amount'] = $transaction['refunded_amount'];
                $dataFormat[] = '%d';
            }

            if (!empty($transaction['refund_information'])) {
                $data['refund_information'] = $transaction['refund_information'];
                $dataFormat[] = '%s';
            }

            if (!empty($transaction['formConfig'])) {
                $data['formConfig'] = $transaction['formConfig'];
                $dataFormat[] = '%s';
            }

            if (!empty($transaction['signature'])) {
                $data['signature'] = $transaction['signature'];
                $dataFormat[] = '%s';
            }

            if (!empty($transaction['spg_style'])) {
                $data['spg_style'] = $transaction['spg_style'];
                $dataFormat[] = '%s';
            }

            if (!empty($transaction['formContext'])) {
                $data['formContext'] = $transaction['formContext'];
                $dataFormat[] = '%s';
            }

            return $wpdb->insert(
                $tableName,
                $data,
                $dataFormat
            );
        }

        return self::update_transaction($wc_order, $transaction);
    }

    /**
     * Save Order Notes
     * save order notes ( database : wp_comment ) if change payment status at backend.
     *
     * @param array $comments commments
     */
    public static function save_order_notes(array $comments)
    {
        global $wpdb;

        $tableName = "{$wpdb->prefix}comments";
        $data = [
            'comment_post_ID' => $comments['order_id'],
            'comment_author' => $comments['author'],
            'comment_author_email' => $comments['email'],
            'comment_date' => SibsConfig::getStoreCurrentTime(),
            'comment_date_gmt' => SibsConfig::getStoreCurrentTime('Y-m-d H:i:s', false, true),
            'comment_content' => $comments['content'],
            'comment_approved' => '1',
            'comment_agent' => 'WooCommerce',
            'comment_type' => 'order_note',
        ];
        $dataFormat = ['%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'];

        return $wpdb->insert(
            $tableName,
            $data,
            $dataFormat
        );
    }

    /**
     * Save Webhook Calls
     * save webhook calls when recieve a new webhook.
     */
    public static function save_webhook_calls(array $webhook)
    {
        global $wpdb;

        $tablePrefix = $wpdb->prefix.Plugin::PLUGIN_PREFIX;
        $tableName = "{$tablePrefix}_webhook_retry";
        $data = [
            'url' => $webhook['url'],
            'headers' => json_encode($webhook['headers']),
            'payload' => $webhook['payload'],
            'created_at' => SibsConfig::getStoreCurrentTime(),
        ];
        $dataFormat = ['%s', '%s', '%s', '%s'];

        $inserted = $wpdb->insert(
            $tableName,
            $data,
            $dataFormat
        );

        return $inserted ? $wpdb->insert_id : false;
    }

    // SAVE OR UPDATE

    /**
     * Save or update Token
     * save or update token ( database : wp_comment ) if change payment status at backend.
     *
     * @param array $token token
     */
    public static function save_or_update_token(array $token)
    {
        global $wpdb;

        $tablePrefix = $wpdb->prefix.Plugin::PLUGIN_PREFIX;
        $tableName = "{$tablePrefix}_card_tokens";
        $data = [
            'id_customer' => get_current_user_id(),
            'value' => $token['value'] ?? '',
            'expire_date_example' => 'PL',
        ];

        if (isset($token['tokenName'])) {
            $data['token_name'] = $token['tokenName'];
        }

        if (isset($token['tokenType'])) {
            $data['token_type'] = $token['tokenType'];
        }

        if (isset($token['maskedPAN'])) {
            $data['masked_pan'] = $token['maskedPAN'];
        }

        if (isset($token['expireDate'])) {
            $data['expire_date'] = $token['expireDate'];
        }

        $where = [
            'id_customer' => get_current_user_id(),
            'value' => $data['value'],
        ];
        $dataFormat = ['%d', '%s', '%s', '%s', '%s', '%s', '%s'];
        $whereFormat = ['%s'];

        $result = $wpdb->update(
            $tableName,
            $data,
            $where,
            $dataFormat,
            $whereFormat
        );

        if (false === $result || $result < 1) {
            return $wpdb->insert($tableName, $data, $dataFormat);
        }

        return $result;
    }
}
