<?php

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

use apexl\Io\modules\payment\entities\paymentTokenEntity;
use apexl\Io\operators\entityDatabaseOperator;

class paymentTokenOperator extends entityDatabaseOperator{

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

    public function fetchAllSetupComplete()
    {
        return $this->vault->select($this->dbTable)->fields(['id','data','provider_data','payment_method_ref','payment_method_ref_iv'])
            ->where('setup_complete', 1)
            ->execute()
            ->fetchAll();
    }

    public function getByUser($userId){
        return $this->vault->select($this->dbTable)->fields()
            ->where('user_id', $userId)
            ->where('deleted', 0)
            ->execute()
            ->fetchAll();
    }

    public function removeDefaultForUser($userId){
        $this->vault->update($this->dbTable)->fields(['default_token' => 0])->where('user_id', $userId)->execute();
    }

    public function getLastForUser($userId){
        return $this->vault->select($this->dbTable)->fields()->where('user_id', $userId)->where('deleted', 0)->orderBy('id', 'DESC')->limit(1)->execute()->fetchAssoc();
    }

    public function getBillingTokenForUser($userId, $provider){

        // 1. Do they have a default token?
        $defaultToken = $this->vault->select($this->dbTable)->fields()->where('provider', $provider)->where('user_id', $userId)->where('default_token', '1')->where('abandoned', '0')->where('setup_complete', '1')->where('deleted', '0')->orderBy('id', 'DESC')->limit(1)->execute()->fetchAssoc();
        if (isset($defaultToken['id']) && $defaultToken['id']) return $defaultToken;

        // 2. Do they have another token with setup complete?
        $token = $this->vault->select($this->dbTable)->fields()->where('provider', $provider)->where('user_id', $userId)->where('abandoned', '0')->where('setup_complete', '1')->where('deleted', '0')->orderBy('id', 'DESC')->limit(1)->execute()->fetchAssoc();
        if (isset($token['id']) && $token['id']) return $token;

        return null;

        // 3. return their last created token
        //return $this->getLastForUser($userId);
    }

    public function getAllActiveForUser($userId){

        return $this->vault->select($this->dbTable)
            ->fields()
            ->where('user_id', $userId)
            ->where('abandoned', '0')
            ->where('setup_complete', '1')
            ->where('deleted', '0')
            ->orderBy('id', 'DESC')
            ->execute()
            ->fetchAll();
    }

    public function abandonToken($tokenId, $reason)
    {
        $this->vault->update($this->dbTable)->fields(['abandoned' => 1, 'abandoned_reason' => $reason])->where('id', $tokenId)->execute();
    }

    public function checkDisableToken($latestToken, int $maxPaymentFailures)
    {
        $tokenId = $latestToken['id'];
        if (!isset($latestToken['payment_method_ref'])
            || $latestToken['setup_complete'] != '1') {
            $this->abandonToken($tokenId, "Setup incomplete, or missing payment provider ref");
            return false;
        }

        if ($tokenId > 0 && $maxPaymentFailures > 1) {
            // Get the last three payments for a token.  If none of them are successful, disable the token
            $payments = $this->vault->select('payment')
                ->fields()
                ->where('payment_token_id', $tokenId)
                ->orderBy('id', 'DESC')
                ->limit($maxPaymentFailures)
                ->execute()
                ->fetchAll();

            if (count($payments) == $maxPaymentFailures) {
                $unsuccessfulCount = 0;
                foreach ($payments as $payment) {
                    if ($payment->status != 'successful') {
                        $unsuccessfulCount++;
                    }
                }
                if ($unsuccessfulCount == $maxPaymentFailures) {
                    $this->abandonToken($tokenId, "Max payment failures reached ({$maxPaymentFailures}). Ref2");
                    return false;
                }
            }
        }

        return $latestToken;

    }

}