<?php
/**
 * Copyright (C) Baluart.COM - All Rights Reserved
 *
 * @since 1.0
 * @author Baluart E.I.R.L.
 * @copyright Copyright (c) 2015 - 2021 Baluart E.I.R.L.
 * @license http://codecanyon.net/licenses/faq Envato marketplace licenses
 * @link https://easyforms.dev/ Easy Forms
 */
namespace app\modules\subscription\services;

use Stripe\Customer;
use Stripe\Event as StripeEvent;
use Stripe\PaymentIntent;
use Stripe\StripeClient as Client;
use Yii;

/**
 * Class StripeClient
 * @package app\modules\subscription\services
 */
class StripeClient
{

    public $client;

    /**
     * StripeClient constructor.
     */
    public function __construct()
    {
        $settings = Yii::$app->settings;

        // Stripe env
        $environment = $settings->get('subscription.environment');

        // Stripe keys
        $publishableKey = $settings->get('subscription.stripeLivePublishableKey');
        $secretKey = $settings->get('subscription.stripeLiveSecretKey');

        if ($environment === 'sandbox') {
            $publishableKey = $settings->get('subscription.stripeSandboxPublishableKey');
            $secretKey = $settings->get('subscription.stripeSandboxSecretKey');
        }

        $this->client = new Client($secretKey);

    }

    /**
     * Create customer
     *
     * @param array $params
     * @return Customer
     * @throws \Stripe\Exception\ApiErrorException
     */
    public function customer(array $params)
    {
        return $this->client->customers->create($params);
    }

    /**
     * Retrieve Plan By ID
     *
     * @param $plan_id
     * @return \Stripe\Plan
     * @throws \Stripe\Exception\ApiErrorException
     */
    public function retrievePlanByID($plan_id)
    {
        return $this->client->plans->retrieve($plan_id);
    }

    /**
     * Create Subscription
     *
     * @param $customer_id
     * @param $items
     * @return \Stripe\Subscription
     * @throws \Stripe\Exception\ApiErrorException
     */
    public function createSubscription($customer_id, $items)
    {
        return $this->client->subscriptions->create([
            'customer' => $customer_id,
            'items' => $items,
        ]);
    }

    /**
     * Get Stripe Subscription
     *
     * @param $subscription_id
     * @return \Stripe\Subscription
     * @throws \Stripe\Exception\ApiErrorException
     */
    public function getSubscription($subscription_id)
    {
        return $this->client->subscriptions->retrieve($subscription_id, []);
    }

    /**
     * Cancel Stripe Subscription
     *
     * @param $subscription_id
     * @return \Stripe\Subscription
     * @throws \Stripe\Exception\ApiErrorException
     */
    public function cancelSubscription($subscription_id)
    {
        return $this->client->subscriptions->cancel($subscription_id, []);
    }

    /**
     * Get Stripe Payment Intent
     *
     * @param $amount
     * @param string $currency_code
     * @return PaymentIntent
     * @throws \Stripe\Exception\ApiErrorException
     */
    public function paymentIntent($amount, $currency_code = 'usd')
    {
        return $this->client->paymentIntents->create([
            'amount' => $amount,
            'currency' => $currency_code,
            // Verify your integration in this guide by including this parameter
            'metadata' => ['integration_check' => 'accept_a_payment'],
        ]);
    }

    /**
     * Confirm Stripe Payment Intent
     *
     * @param $payment_intent_id
     * @return PaymentIntent
     * @throws \Stripe\Exception\ApiErrorException
     */
    public function confirmPaymentIntent($payment_intent_id)
    {
        $intent = $this->client->paymentIntents->retrieve($payment_intent_id);
        // You cannot confirm this PaymentIntent
        // because it has already succeeded after being previously confirmed.
        if (isset($intent->status) && $intent->status !== 'succeeded') {
            return $intent->confirm();
        }
        return $intent;
    }

    /**
     * Retrieve Stripe Event By ID
     *
     * @param $event_id
     * @return StripeEvent
     * @throws \Stripe\Exception\ApiErrorException
     */
    public function retrieveEventByID($event_id)
    {
        return $this->client->events->retrieve($event_id);
    }

    /**
     * Update Stripe Subscription
     *
     * @param $subscription_id
     * @param $new_price_id
     * @return \Stripe\Subscription|null
     * @throws \Stripe\Exception\ApiErrorException
     */
    public function updateSubscription($subscription_id, $new_price_id)
    {
        $subscription = $this->getSubscription($subscription_id);

        if (isset($subscription->items->data[0]->id)) {
            return $this->client->subscriptions->update(
                $subscription_id, [
                    'items' => [[
                        'id' => $subscription->items->data[0]->id,
                        'price' => $new_price_id,
                    ]],
                ]
            );
        }

        return null;
    }

    /**
     * Preview Stripe Invoice
     *
     * @param $subscription_id
     * @param $new_price_id
     * @return \Stripe\Invoice|null
     * @throws \Stripe\Exception\ApiErrorException
     */
    public function previewInvoice($subscription_id, $new_price_id)
    {
        $proration_date = time();

        $subscription = $this->getSubscription($subscription_id);

        if (isset($subscription->items->data[0]->id)) {
            $items = [
                [
                    'id' => $subscription->items->data[0]->id,
                    'price' => $new_price_id, # Switch to new price
                ],
            ];

            return $this->client->invoices->upcoming([
                'customer' => $subscription->customer,
                'subscription' => $subscription_id,
                'subscription_items' => $items,
                'subscription_proration_date' => $proration_date,
            ]);
        }

        return null;
    }
}