<?php

namespace apexl\Io\modules\payment\entities\operators;

use apexl\Io\modules\user\services\currentUser;
use apexl\Io\operators\entityDatabaseOperator;

class paymentOperator extends entityDatabaseOperator{

    public function __construct($table, $primaryKey = 'id')
    {
        parent::__construct($table, $primaryKey);
    }

    public function loadByPublicId($publicId) {
        $entity = $this->vault->select($this->dbTable)->fields()
            ->where('public_id', $publicId)
            ->execute()
            ->fetchAssoc();

        return ['updateEntityData' => true, 'data' => $entity];
    }

    public function loadByProviderRef($providerRef) {
        $entity = $this->vault->select($this->dbTable)->fields()
            ->where('provider_ref', $providerRef)
            ->execute()
            ->fetchAssoc();

        return ['updateEntityData' => true, 'data' => $entity];
    }

    public function loadByRef($ref) {
        $entity = $this->vault->select($this->dbTable)->fields()
            ->where('ref', $ref)
            ->execute()
            ->fetchAssoc();

        return ['updateEntityData' => true, 'data' => $entity];
    }

    public function fetchAllByRef($ref)
    {
        return $this->vault->select($this->dbTable)
            ->fields()
            ->where('ref', $ref)
            ->execute()
            ->fetchAll();
    }

    public function getPaymentNotifications($userId){
        return $this->vault
            ->select($this->dbTable)
            ->fields($this->dbTable.'.*')
            ->join('subscription_payment', 'payment_id', $this->dbTable.'.id')
            ->join('subscription', 'subscription.id', 'subscription_payment.subscription_id')
            ->where('payment.user_notified', false)
            ->where('subscription.user_id', $userId)
            ->execute()
            ->fetchAll();
    }

    public function getPendingPaymentByRemoteOrderId($remoteOrderId){
        return $this->vault
            ->select($this->dbTable)
            ->fields($this->dbTable.'.*')
            ->where('remote_order_id', $remoteOrderId)
            ->where('status', 'pending')
            ->execute()
            ->fetchAssoc();
    }

    public function getMostRecentForSubscription($subscriptionId){
        $result = $this->vault
            ->select($this->dbTable)
            ->fields($this->dbTable.'.*')
            ->join('subscription_payment', 'payment_id', $this->dbTable.'.id')
            ->join('subscription', 'subscription.id', 'subscription_payment.subscription_id')
            ->where('subscription.id', $subscriptionId)
            ->orderBy('created', 'DESC')
            ->execute()
            ->fetchAssoc();
        if ($result) {
            return (object)$result;
        }

        return null;
    }

    public function getMostRecentForUser($userId, $status = [])
    {
        $query = $this->vault
            ->select($this->dbTable)
            ->fields()
            ->where('user_id', $userId);
        if (count($status) > 0) {
            $query->where('status', $status, 'IN');
        }
        $query->orderBy('created', 'DESC');
        $entity = $query->execute()->fetchAssoc();

        return ['updateEntityData' => true, 'data' => $entity];
    }

    public function getActiveThreeDSecurePaymentsForSubscription($subscriptionId){
        return $this->vault
            ->select('payment')
            ->fields('payment.*')
            ->join('subscription_payment', $this->dbTable.'.id=subscription_payment.payment_id', '','')
            ->where('subscription_id', $subscriptionId)
            ->where('status', 'three_d_secure_required')
            ->execute()
            ->fetchAll();

    }

    public function getPaymentSubscriptionsByUser($userId){
        $data = $this->vault->select('subscription_payment')
            ->fields()
            ->join('payment', 'payment.id = subscription_payment.payment_id','','')
            ->where('user_id', $userId)
            ->execute()
            ->fetchAll();
        $results = [];
        foreach ($data as $item) {
            $results[$item->payment_id][] = $item->subscription_id;
        }

        return $results;
    }

    public function getLatestPaymentsViewData($userEntity=null, $remoteOrderId=0, $limit=10)
    {
        $currentUser = currentUser::getCurrentUser();

        $this->vault
            ->select($this->dbTable . ' p')
            ->fields('p.id, DATE_FORMAT(FROM_UNIXTIME(p.created), "%D %b %Y at %H:%i") as paymentDate, TRIM(CONCAT(u.first_name, " ", u.last_name)) as customerName, p.amount, p.status, i.line_items as lineItems, i.remote_order_id, p.provider, p.failure_reason, p.fraudulent, p.risk_level, p.provider_ref, p.provider_ref_2, IF(i.paid=0 AND i.billing_enabled=1 AND i.abandoned=0 AND i.on_hold=0, 1,"") AS next_attempt, i.id as invoice_id, p.user_id')
            ->leftjoin('invoice_payment ip', 'ip.payment_id', 'p.id')
            ->leftjoin('invoice i', 'i.id', 'ip.invoice_id')
            ->leftjoin('users u', 'u.id', 'i.user_id');
        if (!$userEntity) {
        if (!$currentUser->isAllowed('administer')) {
            $this->vault->where('p.user_id', $currentUser->id);
        }
        } else {
            $this->vault->where('p.user_id', $userEntity->id);
        }
        if ($remoteOrderId > 0) {
            $this->vault->where('p.remote_order_id', $remoteOrderId);
        }
        return $this->vault
            ->orderBy('p.created', 'DESC')
            ->limit($limit)
            ->execute()
            ->fetchAll();
    }

    public function getPaymentsForInvoiceIds($invoiceIds)
    {
        return $this->vault
            ->select($this->dbTable . ' p')
            ->fields('p.id, DATE_FORMAT(FROM_UNIXTIME(p.created), "%D %b %Y") as paymentDate, p.amount, p.status, i.line_items as lineItems, i.remote_order_id, p.provider, p.failure_reason, p.fraudulent, p.risk_level, i.id as invoice_id')
            ->leftjoin('invoice_payment ip', 'ip.payment_id', 'p.id')
            ->leftjoin('invoice i', 'i.id', 'ip.invoice_id')
            ->where('i.id', $invoiceIds, 'IN')
            ->orderBy('p.created', 'DESC')
            ->execute()
            ->fetchAll();
    }

    public function getPaymentsForRemoteOrderIds($remoteOrderIds)
    {
        $results = $this->vault
            ->select($this->dbTable)
            ->fields($this->dbTable.'.*')
            ->where('remote_order_id', $remoteOrderIds, 'IN')
            ->execute()
            ->fetchAll();

        $payments = [];
        foreach ($results as $result) {
            $payments[$result->remote_order_id] = $result;
        }

        return $payments;
    }

}